2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char *argv[])
6 | {
7 | @autoreleasepool {
8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/Example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/Example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'RnDiffApp'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 | includeBuild('../node_modules/@react-native/gradle-plugin')
5 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/__tests__/App-test.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import 'react-native';
6 | import React from 'react';
7 | import App from '../App';
8 |
9 | // Note: test renderer must be required after react-native.
10 | import renderer from 'react-test-renderer';
11 |
12 | it('renders correctly', () => {
13 | renderer.create();
14 | });
15 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Example/metro.config.js:
--------------------------------------------------------------------------------
1 | const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
2 |
3 | /**
4 | * Metro configuration
5 | * https://facebook.github.io/metro/docs/configuration
6 | *
7 | * @type {import('metro-config').MetroConfig}
8 | */
9 | const config = {};
10 |
11 | module.exports = mergeConfig(getDefaultConfig(__dirname), config);
12 |
--------------------------------------------------------------------------------
/src/commands/bundle.js:
--------------------------------------------------------------------------------
1 | const esbuild = require('esbuild');
2 | const { emptyDefaultCacheDir } = require('../cache');
3 |
4 | module.exports = (getBundleConfig) => async (_, config, args) => {
5 | if (args.resetCache) {
6 | emptyDefaultCacheDir();
7 | }
8 | const esbuildConfig = getBundleConfig(config, args);
9 | await esbuild.build({
10 | ...esbuildConfig,
11 | bundle: true,
12 | write: true,
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/src/cache.js:
--------------------------------------------------------------------------------
1 | const os = require('os');
2 | const path = require('path');
3 | const fs = require('fs-extra');
4 |
5 | let defaultCacheDir = null;
6 | function getDefaultCacheDir() {
7 | if (!defaultCacheDir) {
8 | defaultCacheDir = path.join(os.tmpdir(), 'react-native-esbuild');
9 | }
10 | return defaultCacheDir;
11 | }
12 |
13 | function emptyDefaultCacheDir() {
14 | fs.emptyDirSync(getDefaultCacheDir());
15 | }
16 |
17 | module.exports = { getDefaultCacheDir, emptyDefaultCacheDir };
18 |
--------------------------------------------------------------------------------
/Example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/Example/ios/.xcode.env:
--------------------------------------------------------------------------------
1 | # This `.xcode.env` file is versioned and is used to source the environment
2 | # used when running script phases inside Xcode.
3 | # To customize your local environment, you can create an `.xcode.env.local`
4 | # file that is not versioned.
5 |
6 | # NODE_BINARY variable contains the PATH to the node executable.
7 | #
8 | # Customize the NODE_BINARY variable here.
9 | # For example, to use nvm with brew, add the following line
10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use
11 | export NODE_BINARY=$(command -v node)
12 |
--------------------------------------------------------------------------------
/src/server/index.js:
--------------------------------------------------------------------------------
1 | const { serveAsset } = require('./assets');
2 | const { createBundler } = require('./bundler');
3 | const { extractBundleParams } = require('./extract-bundle-params');
4 | const { symbolicateStack } = require('./symbolicate');
5 | const { enableInteractiveMode } = require('./interactive-mode');
6 | const { createHMREndpoint } = require('./hmr-endpoint');
7 |
8 | module.exports = {
9 | serveAsset,
10 | createBundler,
11 | extractBundleParams,
12 | symbolicateStack,
13 | enableInteractiveMode,
14 | createHMREndpoint,
15 | };
16 |
--------------------------------------------------------------------------------
/src/plugins/index.js:
--------------------------------------------------------------------------------
1 | const { assetLoaderPlugin } = require('./asset-loader');
2 | const { babelPlugin } = require('./babel');
3 | const {
4 | outOfTreePlatformResolverPlugin,
5 | } = require('./out-of-tree-platform-resolver');
6 | const {
7 | syntaxAwareLoaderPlugin,
8 | defaultHasFlowSyntax,
9 | defaultHasReanimatedSyntax,
10 | } = require('./syntax-aware-loader');
11 |
12 | module.exports = {
13 | assetLoaderPlugin,
14 | babelPlugin,
15 | outOfTreePlatformResolverPlugin,
16 | syntaxAwareLoaderPlugin,
17 | defaultHasFlowSyntax,
18 | defaultHasReanimatedSyntax,
19 | };
20 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const {
2 | assetLoaderPlugin,
3 | babelPlugin,
4 | outOfTreePlatformResolverPlugin,
5 | syntaxAwareLoaderPlugin,
6 | defaultHasFlowSyntax,
7 | defaultHasReanimatedSyntax,
8 | } = require('./plugins');
9 | const { createEsbuildCommands } = require('./commands');
10 |
11 | const commands = createEsbuildCommands();
12 |
13 | module.exports = {
14 | commands,
15 | createEsbuildCommands,
16 | assetLoaderPlugin,
17 | babelPlugin,
18 | outOfTreePlatformResolverPlugin,
19 | syntaxAwareLoaderPlugin,
20 | defaultHasFlowSyntax,
21 | defaultHasReanimatedSyntax,
22 | };
23 |
--------------------------------------------------------------------------------
/Example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/logger.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const chalk = require('chalk');
3 |
4 | const createLog =
5 | (color, log = console.log) =>
6 | (category, message) => {
7 | log(`${color.inverse.bold(` ${category.toUpperCase()} `)} ${message}`);
8 | };
9 |
10 | const defaultLogger = {
11 | log: createLog(chalk.white),
12 | warn: createLog(chalk.yellow),
13 | success: createLog(chalk.green),
14 | error: createLog(chalk.red),
15 | };
16 |
17 | const formatFilePath = (filePath) =>
18 | `${chalk.dim(`${path.dirname(filePath)}/`)}${chalk.bold(
19 | path.basename(filePath)
20 | )}`;
21 |
22 | module.exports = { defaultLogger, formatFilePath };
23 |
--------------------------------------------------------------------------------
/Example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "33.0.0"
6 | minSdkVersion = 21
7 | compileSdkVersion = 33
8 | targetSdkVersion = 33
9 |
10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
11 | ndkVersion = "23.1.7779620"
12 | }
13 | repositories {
14 | google()
15 | mavenCentral()
16 | }
17 | dependencies {
18 | classpath("com.android.tools.build:gradle")
19 | classpath("com.facebook.react:react-native-gradle-plugin")
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/server/extract-bundle-params.js:
--------------------------------------------------------------------------------
1 | const { parse } = require('url');
2 |
3 | function extractBundleParams(url) {
4 | const {
5 | pathname,
6 | query: { platform, dev, minify },
7 | } = parse(url, true);
8 |
9 | if (!pathname.endsWith('.bundle')) {
10 | throw new Error(
11 | `Expected path name to end with .bundle, got "${pathname}"`
12 | );
13 | }
14 |
15 | if (!platform) {
16 | throw new Error(`Expected platform in query parameters`);
17 | }
18 |
19 | return {
20 | platform,
21 | entryFile: pathname.substring(1, pathname.length - 7),
22 | dev: dev !== 'false',
23 | minify: minify === 'true',
24 | };
25 | }
26 |
27 | module.exports = { extractBundleParams };
28 |
--------------------------------------------------------------------------------
/Example/android/app/src/release/java/com/example/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.example;
8 |
9 | import android.content.Context;
10 | import com.facebook.react.ReactInstanceManager;
11 |
12 | /**
13 | * Class responsible of loading Flipper inside your React Native application. This is the release
14 | * flavor of it so it's empty as we don't want to load Flipper.
15 | */
16 | public class ReactNativeFlipper {
17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
18 | // Do nothing as we don't want to initialize Flipper on Release.
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Example/ios/ExampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/server/extract-bundle-params.spec.js:
--------------------------------------------------------------------------------
1 | const { test } = require('uvu');
2 | const assert = require('uvu/assert');
3 | const { extractBundleParams } = require('./extract-bundle-params');
4 |
5 | test('throws for non .bundle urls', () => {
6 | assert.throws(() => extractBundleParams('/index.html?platform=ios'));
7 | });
8 |
9 | test('throws when missing platform in url', () => {
10 | assert.throws(() => extractBundleParams('/index.bundle'));
11 | });
12 |
13 | test('has defaults for dev & minify', () => {
14 | assert.equal(extractBundleParams('/index.bundle?platform=ios'), {
15 | platform: 'ios',
16 | entryFile: 'index',
17 | dev: true,
18 | minify: false,
19 | });
20 | });
21 |
22 | test('ignores additional params', () => {
23 | assert.equal(
24 | extractBundleParams(
25 | '/index.bundle?platform=macos&dev=true&minify=false&modulesOnly=false&runModule=true&app=se.oblador.test'
26 | ),
27 | {
28 | platform: 'macos',
29 | entryFile: 'index',
30 | dev: true,
31 | minify: false,
32 | }
33 | );
34 | });
35 |
36 | test.run();
37 |
--------------------------------------------------------------------------------
/src/config.js:
--------------------------------------------------------------------------------
1 | const ASSETS_PUBLIC_PATH = '/assets/';
2 | const BITMAP_IMAGE_EXTENSIONS = [
3 | '.bmp',
4 | '.gif',
5 | '.jpg',
6 | '.jpeg',
7 | '.png',
8 | '.psd',
9 | '.svg',
10 | '.webp',
11 | ];
12 | const NON_BITMAP_IMAGE_EXTENSIONS = [
13 | // Vector image formats
14 | '.svg',
15 | // Video formats
16 | '.m4v',
17 | '.mov',
18 | '.mp4',
19 | '.mpeg',
20 | '.mpg',
21 | '.webm',
22 | // Audio formats
23 | '.aac',
24 | '.aiff',
25 | '.caf',
26 | '.m4a',
27 | '.mp3',
28 | '.wav',
29 | // Document formats
30 | '.html',
31 | '.pdf',
32 | '.yaml',
33 | '.yml',
34 | // Font formats
35 | '.otf',
36 | '.ttf',
37 | // Archives (virtual files)
38 | '.zip',
39 | ];
40 | const ASSET_EXTENSIONS = BITMAP_IMAGE_EXTENSIONS.concat(
41 | NON_BITMAP_IMAGE_EXTENSIONS
42 | );
43 | const SOURCE_EXTENSIONS = [
44 | '.tsx',
45 | '.ts',
46 | '.jsx',
47 | '.js',
48 | '.mjs',
49 | '.cjs',
50 | '.json',
51 | ];
52 | module.exports = {
53 | ASSETS_PUBLIC_PATH,
54 | BITMAP_IMAGE_EXTENSIONS,
55 | ASSET_EXTENSIONS,
56 | SOURCE_EXTENSIONS,
57 | };
58 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/ios/Example/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "scale" : "1x",
46 | "size" : "1024x1024"
47 | }
48 | ],
49 | "info" : {
50 | "author" : "xcode",
51 | "version" : 1
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2022 Joel Arvidsson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/plugins/out-of-tree-platform-resolver.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const isModuleImport = (moduleName, args) =>
4 | args.path === moduleName || args.path.startsWith(`${moduleName}/`);
5 |
6 | const RN_PACKAGE_NAME = 'react-native';
7 |
8 | const outOfTreePlatformResolverPlugin = ({
9 | filter = /./,
10 | moduleName,
11 | } = {}) => ({
12 | name: 'out-of-tree-platform-resolver',
13 | setup(build) {
14 | if (!moduleName || moduleName === RN_PACKAGE_NAME) {
15 | throw new Error(`Invalid \`moduleName\` argument "${moduleName}"`);
16 | }
17 |
18 | build.onResolve({ filter }, async (args) => {
19 | if (isModuleImport(RN_PACKAGE_NAME, args)) {
20 | const target = `${moduleName}${args.path.slice(
21 | RN_PACKAGE_NAME.length
22 | )}`;
23 |
24 | return await build.resolve(target, {
25 | resolveDir: args.resolveDir,
26 | importer: args.importer,
27 | kind: args.kind,
28 | namespace: args.namespace,
29 | });
30 | }
31 |
32 | return null;
33 | });
34 | },
35 | });
36 |
37 | module.exports = { outOfTreePlatformResolverPlugin };
38 |
--------------------------------------------------------------------------------
/Example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | ios/.xcode.env.local
24 |
25 | # Android/IntelliJ
26 | #
27 | build/
28 | .idea
29 | .gradle
30 | local.properties
31 | *.iml
32 | *.hprof
33 | .cxx/
34 | *.keystore
35 | !debug.keystore
36 |
37 | # node.js
38 | #
39 | node_modules/
40 | npm-debug.log
41 | yarn-error.log
42 |
43 | # fastlane
44 | #
45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
46 | # screenshots whenever they are needed.
47 | # For more information about the recommended setup visit:
48 | # https://docs.fastlane.tools/best-practices/source-control/
49 |
50 | **/fastlane/report.xml
51 | **/fastlane/Preview.html
52 | **/fastlane/screenshots
53 | **/fastlane/test_output
54 |
55 | # Bundle artifact
56 | *.jsbundle
57 |
58 | # Ruby / CocoaPods
59 | /ios/Pods/
60 | /vendor/bundle/
61 |
62 | # Temporary files created by Metro to check the health of the file watcher
63 | .metro-health-check*
64 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/java/com/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import com.facebook.react.ReactActivity;
4 | import com.facebook.react.ReactActivityDelegate;
5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
6 | import com.facebook.react.defaults.DefaultReactActivityDelegate;
7 |
8 | public class MainActivity extends ReactActivity {
9 |
10 | /**
11 | * Returns the name of the main component registered from JavaScript. This is used to schedule
12 | * rendering of the component.
13 | */
14 | @Override
15 | protected String getMainComponentName() {
16 | return "Example";
17 | }
18 |
19 | /**
20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
22 | * (aka React 18) with two boolean flags.
23 | */
24 | @Override
25 | protected ReactActivityDelegate createReactActivityDelegate() {
26 | return new DefaultReactActivityDelegate(
27 | this,
28 | getMainComponentName(),
29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer.
30 | DefaultNewArchitectureEntryPoint.getFabricEnabled());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Example/ios/Example/AppDelegate.mm:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 |
5 | @implementation AppDelegate
6 |
7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
8 | {
9 | self.moduleName = @"Example";
10 | // You can add your custom initial props in the dictionary below.
11 | // They will be passed down to the ViewController used by React Native.
12 | self.initialProps = @{};
13 |
14 | return [super application:application didFinishLaunchingWithOptions:launchOptions];
15 | }
16 |
17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
18 | {
19 | #if DEBUG
20 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
21 | #else
22 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
23 | #endif
24 | }
25 |
26 | /// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
27 | ///
28 | /// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
29 | /// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
30 | /// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`.
31 | - (BOOL)concurrentRootEnabled
32 | {
33 | return true;
34 | }
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/src/server/assets.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const { getMimeType } = require('./mime');
4 |
5 | async function resolvePlatformSpecificFile(requestPath, platform) {
6 | const suffixes = [`.${platform}`, '.native', ''];
7 | const extension = path.extname(requestPath);
8 | const dirname = path.dirname(requestPath);
9 | const basename = path.basename(requestPath, extension);
10 | const files = await fs.promises.readdir(dirname);
11 | for (const suffix of suffixes) {
12 | const filename = `${basename}${suffix}${extension}`;
13 | if (files.includes(filename)) {
14 | return path.join(dirname, filename);
15 | }
16 | }
17 | return null;
18 | }
19 |
20 | async function sendFile(res, filePath) {
21 | const file = await fs.promises.open(filePath, 'r');
22 | try {
23 | const stat = await file.stat();
24 | if (!stat.isFile()) {
25 | throw new Error('Path is directory');
26 | }
27 | const contentType = getMimeType(filePath);
28 |
29 | res.writeHead(200, {
30 | 'Content-Type': contentType,
31 | 'Content-Length': stat.size,
32 | });
33 |
34 | res.end(await file.readFile());
35 | } finally {
36 | file.close();
37 | }
38 | }
39 |
40 | async function serveAsset(res, requestPath, platform) {
41 | const filePath = await resolvePlatformSpecificFile(requestPath, platform);
42 | if (filePath) {
43 | await sendFile(res, filePath);
44 | return true;
45 | }
46 | return false;
47 | }
48 |
49 | module.exports = { serveAsset };
50 |
--------------------------------------------------------------------------------
/src/server/interactive-mode.js:
--------------------------------------------------------------------------------
1 | const readline = require('readline');
2 | const { logger } = require('@react-native-community/cli-tools');
3 |
4 | function printInteractiveModeInstructions() {
5 | logger.log('To reload the app press "r"\nTo open developer menu press "d"\n');
6 | }
7 |
8 | function enableInteractiveMode(messageSocket) {
9 | // We need to set this to true to catch key presses individually.
10 | // As a result we have to implement our own method for exiting
11 | // and other commands (e.g. ctrl+c & ctrl+z)
12 | if (!process.stdin.setRawMode) {
13 | logger.debug('Interactive mode is not supported in this environment');
14 |
15 | return;
16 | }
17 |
18 | readline.emitKeypressEvents(process.stdin);
19 |
20 | process.stdin.setRawMode(true);
21 |
22 | printInteractiveModeInstructions();
23 |
24 | process.stdin.on('keypress', (_key, data) => {
25 | const { ctrl, name } = data;
26 |
27 | if (ctrl === true) {
28 | switch (name) {
29 | case 'c':
30 | process.exit();
31 | break;
32 |
33 | case 'z':
34 | process.emit('SIGTSTP', 'SIGTSTP');
35 | break;
36 | }
37 | } else if (name === 'r') {
38 | messageSocket.broadcast('reload', null);
39 |
40 | logger.info('Reloading app...');
41 | } else if (name === 'd') {
42 | messageSocket.broadcast('devMenu', null);
43 |
44 | logger.info('Opening developer menu...');
45 | } else {
46 | logger.log(_key);
47 | }
48 | });
49 | }
50 |
51 | module.exports = { enableInteractiveMode };
52 |
--------------------------------------------------------------------------------
/.github/workflows/tests.yml:
--------------------------------------------------------------------------------
1 | name: Tests
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | unit:
13 | name: Unit tests
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Setup node
18 | uses: actions/setup-node@v3
19 | with:
20 | node-version: 16
21 | - name: Install npm dependencies
22 | run: yarn --frozen-lockfile --non-interactive --silent --ignore-scripts
23 | - name: Run tests
24 | run: yarn test
25 |
26 | ios:
27 | name: iOS tests
28 | runs-on: macos-latest
29 |
30 | steps:
31 | - uses: actions/checkout@v3
32 | - name: Setup node
33 | uses: actions/setup-node@v3
34 | with:
35 | node-version: 16
36 | - name: Setup ruby
37 | uses: ruby/setup-ruby@v1
38 | with:
39 | ruby-version: '2.7.4'
40 | bundler: '2.2.27'
41 | - name: Install npm dependencies
42 | run: yarn --frozen-lockfile --non-interactive --silent --ignore-scripts
43 | - name: Install Example npm dependencies
44 | run: yarn --frozen-lockfile --non-interactive --silent
45 | working-directory: ./Example
46 | - name: Install Example gem dependencies
47 | working-directory: ./Example
48 | run: bundle install
49 | - name: Install Example cocoapods dependencies
50 | working-directory: ./Example/ios
51 | run: bundle exec pod install
52 | - name: Run tests
53 | run: yarn test-ios
54 |
--------------------------------------------------------------------------------
/src/server/hmr-endpoint.js:
--------------------------------------------------------------------------------
1 | const { Server } = require('ws');
2 |
3 | function createHMREndpoint(logger) {
4 | const server = new Server({ noServer: true });
5 |
6 | let clientSocket;
7 |
8 | function sendSafely(type, body) {
9 | if (clientSocket) {
10 | clientSocket.send(JSON.stringify({ type, body }));
11 | }
12 | }
13 |
14 | function reload() {
15 | // Esbuild doesn't support HMR, but we can hack the update API
16 | // to implement an opt-in live reload functionality
17 | sendSafely('update', {
18 | added: [
19 | {
20 | module: [
21 | 'esbuild_reload_hack',
22 | '(window.__turboModuleProxy ? window.__turboModuleProxy("DevSettings") : window.nativeModuleProxy["DevSettings"]).reload();',
23 | ],
24 | sourceURL: null,
25 | },
26 | ],
27 | deleted: [],
28 | modified: [],
29 | });
30 | }
31 |
32 | const socketCloseHandler = () => {
33 | clientSocket = null;
34 | };
35 |
36 | server.on('connection', (socket, request) => {
37 | clientSocket = socket;
38 | clientSocket.onerror = socketCloseHandler;
39 | clientSocket.onclose = socketCloseHandler;
40 | clientSocket.onmessage = ({ data }) => {
41 | const event = JSON.parse(data);
42 | switch (event.type) {
43 | case 'log':
44 | const log = logger[event.level] || logger.log;
45 | log(event.level, event.data);
46 | break;
47 | }
48 | };
49 | });
50 |
51 | return {
52 | server,
53 | reload,
54 | };
55 | }
56 |
57 | module.exports = { createHMREndpoint };
58 |
--------------------------------------------------------------------------------
/Example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android --no-packager",
7 | "bundle": "rm -rf build && mkdir build && react-native esbuild-bundle --bundle-output ./build/index.bundle --assets-dest ./build",
8 | "ios": "react-native run-ios --no-packager",
9 | "lint": "eslint .",
10 | "postinstall": "DESTINATION='node_modules/react-native-esbuild' LIB_FILE=`cd .. && echo \\`pwd\\`/\\`npm pack\\`` && (rm -rf $DESTINATION || true) && mkdir $DESTINATION && tar -xvzf $LIB_FILE -C $DESTINATION --strip-components 1 && rm $LIB_FILE",
11 | "start": "react-native esbuild-start",
12 | "test": "jest"
13 | },
14 | "dependencies": {
15 | "esbuild": "^0.18.11",
16 | "nanoid": "^4.0.2",
17 | "react": "18.2.0",
18 | "react-native": "0.72.1",
19 | "react-native-get-random-values": "^1.8.0",
20 | "react-native-reanimated": "^3.3.0"
21 | },
22 | "devDependencies": {
23 | "@babel/core": "^7.20.0",
24 | "@babel/preset-env": "^7.20.0",
25 | "@babel/runtime": "^7.20.0",
26 | "@react-native/eslint-config": "^0.72.2",
27 | "@react-native/metro-config": "^0.72.7",
28 | "@tsconfig/react-native": "^3.0.0",
29 | "@types/jest": "^29.2.1",
30 | "@types/react": "^18.0.24",
31 | "@types/react-test-renderer": "^18.0.0",
32 | "babel-jest": "^29.2.1",
33 | "eslint": "^8.19.0",
34 | "jest": "^29.2.1",
35 | "metro-react-native-babel-preset": "0.76.5",
36 | "prettier": "^2.4.1",
37 | "react-test-renderer": "18.2.0",
38 | "typescript": "4.8.4"
39 | },
40 | "engines": {
41 | "node": ">=16"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Example/ios/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | Example
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | $(CURRENT_PROJECT_VERSION)
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSExceptionDomains
30 |
31 | localhost
32 |
33 | NSExceptionAllowsInsecureHTTPLoads
34 |
35 |
36 |
37 |
38 | NSLocationWhenInUseUsageDescription
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UIViewControllerBasedStatusBarAppearance
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-esbuild",
3 | "version": "0.6.0",
4 | "description": "Fast bundler and dev server for react-native using esbuild",
5 | "main": "src/index",
6 | "scripts": {
7 | "format": "prettier src --write",
8 | "test": "uvu src .spec.js",
9 | "test-ios": "FORCE_BUNDLING=1 RCT_NO_LAUNCH_PACKAGER=1 xcodebuild test -workspace Example/ios/Example.xcworkspace -scheme 'Example' -destination 'platform=iOS Simulator,name=iPhone 14'"
10 | },
11 | "author": {
12 | "name": "Joel Arvidsson",
13 | "email": "joel@oblador.se"
14 | },
15 | "homepage": "https://github.com/oblador/react-native-esbuild",
16 | "bugs": {
17 | "url": "https://github.com/oblador/react-native-esbuild/issues"
18 | },
19 | "repository": {
20 | "type": "git",
21 | "url": "git://github.com/oblador/react-native-esbuild.git"
22 | },
23 | "license": "MIT",
24 | "files": [
25 | "src/**/*.js",
26 | "!src/**/*.spec.js"
27 | ],
28 | "keywords": [
29 | "react-native",
30 | "esbuild",
31 | "dev-server",
32 | "development",
33 | "bundler"
34 | ],
35 | "dependencies": {
36 | "@babel/code-frame": "^7.16.7",
37 | "@babel/plugin-syntax-flow": "^7.17.12",
38 | "@babel/plugin-syntax-jsx": "^7.17.12",
39 | "@babel/plugin-transform-flow-strip-types": "^7.17.12",
40 | "@react-native-community/cli-server-api": "^8.0.0",
41 | "@react-native-community/cli-tools": "^8.0.0",
42 | "chalk": "^4.1.2",
43 | "fs-extra": "^10.1.0",
44 | "image-size": "^1.0.1",
45 | "source-map": "^0.7.4"
46 | },
47 | "devDependencies": {
48 | "@babel/core": "^7.18.0",
49 | "@react-native/polyfills": "^2.0.0",
50 | "esbuild": "^0.17.16",
51 | "prettier": "^2.6.2",
52 | "uvu": "^0.5.3"
53 | },
54 | "peerDependencies": {
55 | "@babel/core": ">=7.0.0",
56 | "esbuild": ">=0.17"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/plugins/asset-destination.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const scaleAssetSuffixMap = {
4 | 0.75: 'ldpi',
5 | 1: 'mdpi',
6 | 1.5: 'hdpi',
7 | 2: 'xhdpi',
8 | 3: 'xxhdpi',
9 | 4: 'xxxhdpi',
10 | };
11 |
12 | const drawableExtensions = new Set([
13 | '.gif',
14 | '.jpeg',
15 | '.jpg',
16 | '.png',
17 | '.webp',
18 | '.xml',
19 | ]);
20 |
21 | function getAndroidResourceFolderName(asset, scale) {
22 | if (!drawableExtensions.has(asset.extension)) {
23 | return 'raw';
24 | }
25 | const suffix = scaleAssetSuffixMap[scale];
26 | if (!suffix) {
27 | throw new Error(
28 | `Don't know which android drawable suffix to use for asset: ${JSON.stringify(
29 | asset
30 | )}`
31 | );
32 | }
33 | return `drawable-${suffix}`;
34 | }
35 |
36 | function getAndroidResourceIdentifier(asset) {
37 | const folderPath = getBasePath(asset);
38 | return `${folderPath}/${asset.basename}`
39 | .toLowerCase()
40 | .replace(/\//g, '_')
41 | .replace(/([^a-z0-9_])/g, '')
42 | .replace(/^assets_/, '');
43 | }
44 |
45 | function getBasePath(asset) {
46 | const basePath = asset.httpServerLocation;
47 | if (basePath[0] === '/') {
48 | return basePath.substr(1);
49 | }
50 | return basePath;
51 | }
52 |
53 | function getAssetDestinationPath(asset, scale, platform) {
54 | if (platform === 'android') {
55 | const androidFolder = getAndroidResourceFolderName(asset, scale);
56 | const fileName = getAndroidResourceIdentifier(asset);
57 | return path.join(androidFolder, `${fileName}${asset.extension}`);
58 | }
59 |
60 | const assetFolder = asset.httpServerLocation
61 | .substr(1)
62 | .replace(/\.\.\//g, '_');
63 | return path.join(
64 | assetFolder,
65 | `${asset.basename}${scale === '1' ? '' : `@${scale}x`}${asset.extension}`
66 | );
67 | }
68 |
69 | module.exports = {
70 | getAssetDestinationPath,
71 | };
72 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/res/drawable/rn_edit_text_material.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
22 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.182.0
29 |
30 | # Use this property to specify which architecture you want to build.
31 | # You can also override it from the CLI using
32 | # ./gradlew -PreactNativeArchitectures=x86_64
33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
34 |
35 | # Use this property to enable support to the new architecture.
36 | # This will allow you to use TurboModules and the Fabric render in
37 | # your application. You should enable this flag either if you want
38 | # to write custom TurboModules/Fabric components OR use libraries that
39 | # are providing them.
40 | newArchEnabled=false
41 |
42 | # Use this property to enable or disable the Hermes JS engine.
43 | # If set to false, you will be using JSC instead.
44 | hermesEnabled=false
45 |
--------------------------------------------------------------------------------
/Example/android/app/src/main/java/com/example/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import android.app.Application;
4 | import com.facebook.react.PackageList;
5 | import com.facebook.react.ReactApplication;
6 | import com.facebook.react.ReactNativeHost;
7 | import com.facebook.react.ReactPackage;
8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
9 | import com.facebook.react.defaults.DefaultReactNativeHost;
10 | import com.facebook.soloader.SoLoader;
11 | import java.util.List;
12 |
13 | public class MainApplication extends Application implements ReactApplication {
14 |
15 | private final ReactNativeHost mReactNativeHost =
16 | new DefaultReactNativeHost(this) {
17 | @Override
18 | public boolean getUseDeveloperSupport() {
19 | return BuildConfig.DEBUG;
20 | }
21 |
22 | @Override
23 | protected List getPackages() {
24 | @SuppressWarnings("UnnecessaryLocalVariable")
25 | List packages = new PackageList(this).getPackages();
26 | // Packages that cannot be autolinked yet can be added manually here, for example:
27 | // packages.add(new MyReactNativePackage());
28 | return packages;
29 | }
30 |
31 | @Override
32 | protected String getJSMainModuleName() {
33 | return "index";
34 | }
35 |
36 | @Override
37 | protected boolean isNewArchEnabled() {
38 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
39 | }
40 |
41 | @Override
42 | protected Boolean isHermesEnabled() {
43 | return BuildConfig.IS_HERMES_ENABLED;
44 | }
45 | };
46 |
47 | @Override
48 | public ReactNativeHost getReactNativeHost() {
49 | return mReactNativeHost;
50 | }
51 |
52 | @Override
53 | public void onCreate() {
54 | super.onCreate();
55 | SoLoader.init(this, /* native exopackage */ false);
56 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
57 | // If you opted-in for the New Architecture, we load the native entry point for this app.
58 | DefaultNewArchitectureEntryPoint.load();
59 | }
60 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Example/ios/ExampleTests/ExampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to\nReact Native"
9 |
10 | @interface ExampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation ExampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(
38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
39 | if (level >= RCTLogLevelError) {
40 | redboxError = message;
41 | }
42 | });
43 | #endif
44 |
45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
48 |
49 | foundElement = [self findSubviewInView:vc.view
50 | matching:^BOOL(UIView *view) {
51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
52 | return YES;
53 | }
54 | return NO;
55 | }];
56 | }
57 |
58 | #ifdef DEBUG
59 | RCTSetLogFunction(RCTDefaultLogFunction);
60 | #endif
61 |
62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/Example/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Disable Flipper by default
2 | if !ENV['NO_FLIPPER']
3 | ENV['NO_FLIPPER'] = "1"
4 | end
5 | # Disable Hermes by default
6 | if !ENV['USE_HERMES']
7 | ENV['USE_HERMES'] = "0"
8 | end
9 |
10 | # Resolve react_native_pods.rb with node to allow for hoisting
11 | require Pod::Executable.execute_command('node', ['-p',
12 | 'require.resolve(
13 | "react-native/scripts/react_native_pods.rb",
14 | {paths: [process.argv[1]]},
15 | )', __dir__]).strip
16 |
17 | platform :ios, min_ios_version_supported
18 | prepare_react_native_project!
19 |
20 | # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
21 | # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
22 | #
23 | # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
24 | # ```js
25 | # module.exports = {
26 | # dependencies: {
27 | # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
28 | # ```
29 | flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
30 |
31 | linkage = ENV['USE_FRAMEWORKS']
32 | if linkage != nil
33 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
34 | use_frameworks! :linkage => linkage.to_sym
35 | end
36 |
37 | target 'Example' do
38 | config = use_native_modules!
39 |
40 | # Flags change depending on the env values.
41 | flags = get_default_flags()
42 |
43 | use_react_native!(
44 | :path => config[:reactNativePath],
45 | # Hermes is now enabled by default. Disable by setting this flag to false.
46 | :hermes_enabled => flags[:hermes_enabled],
47 | :fabric_enabled => flags[:fabric_enabled],
48 | # Enables Flipper.
49 | #
50 | # Note that if you have use_frameworks! enabled, Flipper will not work and
51 | # you should disable the next line.
52 | :flipper_configuration => flipper_config,
53 | # An absolute path to your application root.
54 | :app_path => "#{Pod::Config.instance.installation_root}/.."
55 | )
56 |
57 | target 'ExampleTests' do
58 | inherit! :complete
59 | # Pods for testing
60 | end
61 |
62 | post_install do |installer|
63 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
64 | react_native_post_install(
65 | installer,
66 | config[:reactNativePath],
67 | :mac_catalyst_enabled => false
68 | )
69 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/src/server/mime.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | function getMimeType(filePath) {
4 | switch (path.extname(filePath).substring(1)) {
5 | case 'gz':
6 | return 'application/gzip';
7 | case 'js':
8 | case 'mjs':
9 | case 'bundle':
10 | return 'application/javascript';
11 | case 'json':
12 | case 'map':
13 | return 'application/json';
14 | case 'cjs':
15 | return 'application/node';
16 | case 'pdf':
17 | return 'application/pdf';
18 | case 'mp4s':
19 | case 'm4p':
20 | return 'application/mp4';
21 | case 'zip':
22 | return 'application/zip';
23 | case 'm4a':
24 | case 'mp4a':
25 | return 'audio/mp4';
26 | case 'mpga':
27 | case 'mp2':
28 | case 'mp2a':
29 | case 'mp3':
30 | case 'm2a':
31 | case 'm3a':
32 | return 'audio/mpeg';
33 | case 'oga':
34 | case 'ogg':
35 | case 'spx':
36 | case 'opus':
37 | return 'audio/ogg';
38 | case 'sil':
39 | return 'audio/silk';
40 | case 'wav':
41 | return 'audio/wav';
42 | case 'weba':
43 | return 'audio/webm';
44 | case 'ttc':
45 | return 'font/collection';
46 | case 'otf':
47 | return 'font/otf';
48 | case 'ttf':
49 | return 'font/ttf';
50 | case 'woff':
51 | return 'font/woff';
52 | case 'woff2':
53 | return 'font/woff2';
54 | case 'gif':
55 | return 'image/gif';
56 | case 'heic':
57 | return 'image/heic';
58 | case 'heics':
59 | return 'image/heic-sequence';
60 | case 'heif':
61 | return 'image/heif';
62 | case 'heifs':
63 | return 'image/heif-sequence';
64 | case 'jp2':
65 | case 'jpg2':
66 | return 'image/jp2';
67 | case 'jpeg':
68 | case 'jpg':
69 | case 'jpe':
70 | return 'image/jpeg';
71 | case 'png':
72 | return 'image/png';
73 | case 'svg':
74 | case 'svgz':
75 | return 'image/svg+xml';
76 | case 'tif':
77 | case 'tiff':
78 | return 'image/tiff';
79 | case 'webp':
80 | return 'image/webp';
81 | case 'mp4':
82 | case 'mp4v':
83 | case 'mpg4':
84 | return 'video/mp4';
85 | case 'mpeg':
86 | case 'mpg':
87 | case 'mpe':
88 | case 'm1v':
89 | case 'm2v':
90 | return 'video/mpeg';
91 | case 'ogv':
92 | return 'video/ogg';
93 | case 'qt':
94 | case 'mov':
95 | return 'video/quicktime';
96 | case 'webm':
97 | return 'video/webm';
98 | }
99 | }
100 |
101 | module.exports = { getMimeType };
102 |
--------------------------------------------------------------------------------
/src/server/symbolicate.js:
--------------------------------------------------------------------------------
1 | const { codeFrameColumns } = require('@babel/code-frame');
2 |
3 | function isBundleFrame(frame) {
4 | return frame.file && frame.file.startsWith('http');
5 | }
6 |
7 | function processFrame(sourceMapConsumer, frame) {
8 | if (!frame.lineNumber || !frame.column) {
9 | return frame;
10 | }
11 |
12 | const lookup = sourceMapConsumer.originalPositionFor({
13 | line: frame.lineNumber,
14 | column: frame.column,
15 | });
16 |
17 | if (!lookup.source) {
18 | return frame;
19 | }
20 |
21 | return {
22 | lineNumber: lookup.line || frame.lineNumber,
23 | column: lookup.column || frame.column,
24 | file: lookup.source,
25 | methodName: lookup.name || frame.methodName,
26 | };
27 | }
28 |
29 | const INTERNAL_CALLSITES_REGEX = new RegExp(
30 | [
31 | '/Libraries/Renderer/implementations/.+\\.js$',
32 | '/Libraries/BatchedBridge/MessageQueue\\.js$',
33 | '/Libraries/YellowBox/.+\\.js$',
34 | '/Libraries/LogBox/.+\\.js$',
35 | '/Libraries/Core/Timers/.+\\.js$',
36 | '/node_modules/react-devtools-core/.+\\.js$',
37 | '/node_modules/react-refresh/.+\\.js$',
38 | '/node_modules/scheduler/.+\\.js$',
39 | ].join('|')
40 | );
41 |
42 | const ESBUILD_FUNCTIONS = ['__async', '__init', '__require'];
43 |
44 | function collapseReactFrame(frame) {
45 | const collapse =
46 | Boolean(frame.file && INTERNAL_CALLSITES_REGEX.test(frame.file)) ||
47 | ESBUILD_FUNCTIONS.includes(frame.methodName);
48 | return { ...frame, collapse };
49 | }
50 |
51 | function getCodeFrame(sourceMapConsumer, frames) {
52 | const frame = frames.find((f) => !f.collapse && f.lineNumber && f.column);
53 | if (!frame) {
54 | return;
55 | }
56 | const { file, column, lineNumber } = frame;
57 | try {
58 | const source = sourceMapConsumer.sourceContentFor(file);
59 |
60 | return {
61 | content: codeFrameColumns(
62 | source,
63 | {
64 | start: { column, line: lineNumber },
65 | },
66 | { forceColor: true }
67 | ),
68 | location: { column, row: lineNumber },
69 | fileName: file,
70 | };
71 | } catch (error) {
72 | console.error('Failed to create code frame: ' + error.message);
73 | }
74 | }
75 |
76 | function symbolicateStack(sourceMapConsumer, stack) {
77 | const frames = stack
78 | .filter(isBundleFrame)
79 | .map((frame) => processFrame(sourceMapConsumer, frame))
80 | .map(collapseReactFrame);
81 |
82 | const codeFrame = getCodeFrame(sourceMapConsumer, frames);
83 |
84 | return {
85 | stack: frames,
86 | codeFrame: codeFrame || null,
87 | };
88 | }
89 |
90 | module.exports = { symbolicateStack };
91 |
--------------------------------------------------------------------------------
/Example/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.6)
5 | rexml
6 | activesupport (7.0.4.3)
7 | concurrent-ruby (~> 1.0, >= 1.0.2)
8 | i18n (>= 1.6, < 2)
9 | minitest (>= 5.1)
10 | tzinfo (~> 2.0)
11 | addressable (2.8.4)
12 | public_suffix (>= 2.0.2, < 6.0)
13 | algoliasearch (1.27.5)
14 | httpclient (~> 2.8, >= 2.8.3)
15 | json (>= 1.5.1)
16 | atomos (0.1.3)
17 | claide (1.1.0)
18 | cocoapods (1.12.0)
19 | addressable (~> 2.8)
20 | claide (>= 1.0.2, < 2.0)
21 | cocoapods-core (= 1.12.0)
22 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
23 | cocoapods-downloader (>= 1.6.0, < 2.0)
24 | cocoapods-plugins (>= 1.0.0, < 2.0)
25 | cocoapods-search (>= 1.0.0, < 2.0)
26 | cocoapods-trunk (>= 1.6.0, < 2.0)
27 | cocoapods-try (>= 1.1.0, < 2.0)
28 | colored2 (~> 3.1)
29 | escape (~> 0.0.4)
30 | fourflusher (>= 2.3.0, < 3.0)
31 | gh_inspector (~> 1.0)
32 | molinillo (~> 0.8.0)
33 | nap (~> 1.0)
34 | ruby-macho (>= 2.3.0, < 3.0)
35 | xcodeproj (>= 1.21.0, < 2.0)
36 | cocoapods-core (1.12.0)
37 | activesupport (>= 5.0, < 8)
38 | addressable (~> 2.8)
39 | algoliasearch (~> 1.0)
40 | concurrent-ruby (~> 1.1)
41 | fuzzy_match (~> 2.0.4)
42 | nap (~> 1.0)
43 | netrc (~> 0.11)
44 | public_suffix (~> 4.0)
45 | typhoeus (~> 1.0)
46 | cocoapods-deintegrate (1.0.5)
47 | cocoapods-downloader (1.6.3)
48 | cocoapods-plugins (1.0.0)
49 | nap
50 | cocoapods-search (1.0.1)
51 | cocoapods-trunk (1.6.0)
52 | nap (>= 0.8, < 2.0)
53 | netrc (~> 0.11)
54 | cocoapods-try (1.2.0)
55 | colored2 (3.1.2)
56 | concurrent-ruby (1.2.2)
57 | escape (0.0.4)
58 | ethon (0.16.0)
59 | ffi (>= 1.15.0)
60 | ffi (1.15.5)
61 | fourflusher (2.3.1)
62 | fuzzy_match (2.0.4)
63 | gh_inspector (1.1.3)
64 | httpclient (2.8.3)
65 | i18n (1.12.0)
66 | concurrent-ruby (~> 1.0)
67 | json (2.6.3)
68 | minitest (5.18.0)
69 | molinillo (0.8.0)
70 | nanaimo (0.3.0)
71 | nap (1.1.0)
72 | netrc (0.11.0)
73 | public_suffix (4.0.7)
74 | rexml (3.2.5)
75 | ruby-macho (2.5.1)
76 | typhoeus (1.4.0)
77 | ethon (>= 0.9.0)
78 | tzinfo (2.0.6)
79 | concurrent-ruby (~> 1.0)
80 | xcodeproj (1.22.0)
81 | CFPropertyList (>= 2.3.3, < 4.0)
82 | atomos (~> 0.1.3)
83 | claide (>= 1.0.2, < 2.0)
84 | colored2 (~> 3.1)
85 | nanaimo (~> 0.3.0)
86 | rexml (~> 3.2.4)
87 |
88 | PLATFORMS
89 | ruby
90 |
91 | DEPENDENCIES
92 | cocoapods (>= 1.11.3)
93 |
94 | RUBY VERSION
95 | ruby 2.7.4p191
96 |
97 | BUNDLED WITH
98 | 2.2.27
99 |
--------------------------------------------------------------------------------
/src/plugins/babel.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const crypto = require('crypto');
3 | const { outputFile } = require('fs-extra');
4 | const fs = require('fs');
5 | const babel = require('@babel/core');
6 | const { getDefaultCacheDir } = require('../cache');
7 |
8 | const md5 = (string) => crypto.createHash('md5').update(string).digest('hex');
9 |
10 | const babelPlugin = (options = {}) => ({
11 | name: 'babel',
12 | setup(build, { transform } = {}) {
13 | const {
14 | filter = /.*/,
15 | namespace = '',
16 | cache = true,
17 | loader = 'js',
18 | config = {},
19 | } = options;
20 | const transformCache = new Map();
21 |
22 | const transformContents = async ({ args, contents }) => {
23 | const babelOptions = babel.loadOptions({
24 | minified: false,
25 | compact: false,
26 | ...config,
27 | sourceMaps: 'inline',
28 | filename: args.path,
29 | caller: {
30 | name: 'esbuild-plugin-babel',
31 | supportsStaticESM: true,
32 | },
33 | });
34 | if (!babelOptions) {
35 | return { contents };
36 | }
37 |
38 | if (babelOptions.sourceMaps) {
39 | const filename = path.relative(process.cwd(), args.path);
40 |
41 | babelOptions.sourceFileName = filename;
42 | }
43 |
44 | const transformWithBabel = () =>
45 | new Promise((resolve, reject) => {
46 | babel.transform(contents, babelOptions, (error, result) => {
47 | error ? reject(error) : resolve(result.code);
48 | });
49 | });
50 |
51 | if (cache) {
52 | const cachePath = path.join(
53 | typeof cache === 'string' ? cache : getDefaultCacheDir(),
54 | md5(JSON.stringify(babelOptions) + contents)
55 | );
56 | try {
57 | return await fs.promises.readFile(cachePath, { encoding: 'utf8' });
58 | } catch (err) {
59 | const transformed = await transformWithBabel();
60 | await outputFile(cachePath, transformed);
61 | return transformed;
62 | }
63 | }
64 | return transformWithBabel();
65 | };
66 |
67 | build.onLoad({ filter, namespace }, async (args) => {
68 | let handle;
69 | try {
70 | handle = await fs.promises.open(args.path, 'r');
71 | let entry = transformCache.get(args.path);
72 | const stats = await handle.stat();
73 |
74 | // Use in-memory cache unless file was modified.
75 | // Ideally we'd compare file contents, but it would be
76 | // slower and is already done by the file system cache
77 | if (!entry || entry.mtimeMs !== stats.mtimeMs) {
78 | const contents = await handle.readFile('utf8');
79 | const transformed = await transformContents({ args, contents });
80 | entry = { transformed, mtimeMs: stats.mtimeMs };
81 | if (cache) {
82 | transformCache.set(args.path, entry);
83 | }
84 | }
85 |
86 | return { contents: entry.transformed, loader };
87 | } finally {
88 | if (handle) {
89 | handle.close();
90 | }
91 | }
92 | });
93 | },
94 | });
95 |
96 | module.exports = { babelPlugin };
97 |
--------------------------------------------------------------------------------
/Example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%"=="" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%"=="" set DIRNAME=.
29 | @rem This is normally unused
30 | set APP_BASE_NAME=%~n0
31 | set APP_HOME=%DIRNAME%
32 |
33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
35 |
36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
38 |
39 | @rem Find java.exe
40 | if defined JAVA_HOME goto findJavaFromJavaHome
41 |
42 | set JAVA_EXE=java.exe
43 | %JAVA_EXE% -version >NUL 2>&1
44 | if %ERRORLEVEL% equ 0 goto execute
45 |
46 | echo.
47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
48 | echo.
49 | echo Please set the JAVA_HOME variable in your environment to match the
50 | echo location of your Java installation.
51 |
52 | goto fail
53 |
54 | :findJavaFromJavaHome
55 | set JAVA_HOME=%JAVA_HOME:"=%
56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
57 |
58 | if exist "%JAVA_EXE%" goto execute
59 |
60 | echo.
61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
62 | echo.
63 | echo Please set the JAVA_HOME variable in your environment to match the
64 | echo location of your Java installation.
65 |
66 | goto fail
67 |
68 | :execute
69 | @rem Setup the command line
70 |
71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
72 |
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if %ERRORLEVEL% equ 0 goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | set EXIT_CODE=%ERRORLEVEL%
85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
87 | exit /b %EXIT_CODE%
88 |
89 | :mainEnd
90 | if "%OS%"=="Windows_NT" endlocal
91 |
92 | :omega
93 |
--------------------------------------------------------------------------------
/src/esbuild-config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { assetLoaderPlugin } = require('./plugins/asset-loader');
3 | const { syntaxAwareLoaderPlugin } = require('./plugins/syntax-aware-loader');
4 | const {
5 | outOfTreePlatformResolverPlugin,
6 | } = require('./plugins/out-of-tree-platform-resolver');
7 | const {
8 | ASSET_EXTENSIONS,
9 | SOURCE_EXTENSIONS,
10 | BITMAP_IMAGE_EXTENSIONS,
11 | } = require('./config');
12 |
13 | function getEsbuildConfig(config, args) {
14 | const {
15 | entryFile,
16 | platform,
17 | dev,
18 | minify,
19 | bundleOutput,
20 | assetsDest,
21 | sourcemapOutput,
22 | } = args;
23 |
24 | if (!config.platforms[platform]) {
25 | throw new Error(
26 | `Invalid platform "${platform}", expected one of ${Object.keys(
27 | config.platforms
28 | ).join(', ')}`
29 | );
30 | }
31 |
32 | const platforms = [platform, 'native', 'react-native'];
33 | const extensions = SOURCE_EXTENSIONS.concat(ASSET_EXTENSIONS);
34 | const resolveExtensions = platforms
35 | .map((p) => extensions.map((e) => `.${p}${e}`))
36 | .concat(extensions)
37 | .flat();
38 |
39 | const outOfTreeReactNativeModuleName =
40 | config.platforms[platform].npmPackageName;
41 | const resolveReactNativePath = (p) =>
42 | outOfTreeReactNativeModuleName
43 | ? require.resolve(path.join(outOfTreeReactNativeModuleName, p))
44 | : path.join(config.reactNativePath, p);
45 |
46 | return {
47 | mainFields: ['react-native', 'browser', 'module', 'main'],
48 | entryPoints: [entryFile],
49 | outfile: bundleOutput,
50 | sourceRoot: config.root,
51 | sourcemap: Boolean(sourcemapOutput),
52 | minify: typeof minify === 'boolean' ? minify : !dev,
53 | resolveExtensions,
54 | define: {
55 | __DEV__: JSON.stringify(dev),
56 | global: 'window',
57 | 'process.env.NODE_ENV': JSON.stringify(
58 | dev ? 'development' : 'production'
59 | ),
60 | },
61 | loader: {
62 | '.js': 'jsx',
63 | ...Object.fromEntries(ASSET_EXTENSIONS.map((ext) => [ext, 'file'])),
64 | },
65 | legalComments: 'none',
66 | banner: {
67 | js: `var __BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date.now(); var window = typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : this;`,
68 | },
69 | inject: [
70 | ...require(resolveReactNativePath('rn-get-polyfills'))(),
71 | resolveReactNativePath('Libraries/Core/InitializeCore.js'),
72 | ],
73 | target: 'es6',
74 | format: 'iife',
75 | plugins: [
76 | outOfTreeReactNativeModuleName &&
77 | outOfTreePlatformResolverPlugin({
78 | moduleName: outOfTreeReactNativeModuleName,
79 | }),
80 | assetLoaderPlugin({
81 | extensions: ASSET_EXTENSIONS,
82 | scalableExtensions: BITMAP_IMAGE_EXTENSIONS,
83 | platform,
84 | rootdir: config.root,
85 | outdir: assetsDest,
86 | dev,
87 | }),
88 | syntaxAwareLoaderPlugin({
89 | filter: /\.([mc]js|[tj]sx?)$/,
90 | cache: dev,
91 | }),
92 | ].filter(Boolean),
93 | };
94 | }
95 |
96 | module.exports = { getEsbuildConfig };
97 |
--------------------------------------------------------------------------------
/src/commands/index.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const { getEsbuildConfig } = require('../esbuild-config');
3 |
4 | function createEsbuildCommands(
5 | enhanceEsbuildConfig = (esbuildConfig) => esbuildConfig
6 | ) {
7 | const getEnhancedEsbuildConfig = (config, args) =>
8 | enhanceEsbuildConfig(getEsbuildConfig(config, args), args);
9 |
10 | return [
11 | {
12 | name: 'esbuild-bundle',
13 | func: require('./bundle')(getEnhancedEsbuildConfig),
14 | options: [
15 | {
16 | name: '--entry-file ',
17 | description:
18 | 'Path to the root JS file, either absolute or relative to JS root',
19 | default: 'index.js',
20 | },
21 | {
22 | name: '--platform ',
23 | description: 'Either "ios" or "android"',
24 | default: 'ios',
25 | },
26 | {
27 | name: '--dev [boolean]',
28 | description:
29 | 'If false, warnings are disabled and the bundle is minified',
30 | parse: (val) => val !== 'false',
31 | default: true,
32 | },
33 | {
34 | name: '--minify [boolean]',
35 | description:
36 | 'Allows overriding whether bundle is minified. This defaults to ' +
37 | 'false if dev is true, and true if dev is false. Disabling minification ' +
38 | 'can be useful for speeding up production builds for testing purposes.',
39 | parse: (val) => val !== 'false',
40 | },
41 | {
42 | name: '--bundle-output ',
43 | description:
44 | 'File name where to store the resulting bundle, ex. /tmp/groups.bundle',
45 | },
46 | {
47 | name: '--sourcemap-output ',
48 | description:
49 | 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',
50 | },
51 | {
52 | name: '--assets-dest ',
53 | description:
54 | 'Directory name where to store assets referenced in the bundle',
55 | },
56 | {
57 | name: '--reset-cache, --resetCache',
58 | description: 'Removes cached files',
59 | default: false,
60 | },
61 | ],
62 | description: 'builds the javascript bundle for offline use',
63 | },
64 | {
65 | name: 'esbuild-start',
66 | func: require('./start')(getEnhancedEsbuildConfig),
67 | options: [
68 | {
69 | name: '--port ',
70 | parse: Number,
71 | },
72 | {
73 | name: '--host ',
74 | },
75 | {
76 | name: '--projectRoot ',
77 | description: 'Path to a custom project root',
78 | parse: (val) => path.resolve(val),
79 | },
80 | {
81 | name: '--reset-cache, --resetCache',
82 | description: 'Removes cached files',
83 | default: false,
84 | },
85 | {
86 | name: '--no-interactive',
87 | description: 'Disables interactive mode',
88 | },
89 | ],
90 | description: 'Starts the development server with esbuild as bundler',
91 | },
92 | ];
93 | }
94 |
95 | module.exports = { createEsbuildCommands };
96 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/Example/android/app/src/debug/java/com/example/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Meta Platforms, Inc. and affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.example;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
21 | import com.facebook.react.ReactInstanceEventListener;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | /**
28 | * Class responsible of loading Flipper inside your React Native application. This is the debug
29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup.
30 | */
31 | public class ReactNativeFlipper {
32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
33 | if (FlipperUtils.shouldEnableFlipper(context)) {
34 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
35 |
36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
37 | client.addPlugin(new DatabasesFlipperPlugin(context));
38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
39 | client.addPlugin(CrashReporterPlugin.getInstance());
40 |
41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
42 | NetworkingModule.setCustomClientBuilder(
43 | new NetworkingModule.CustomClientBuilder() {
44 | @Override
45 | public void apply(OkHttpClient.Builder builder) {
46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
47 | }
48 | });
49 | client.addPlugin(networkFlipperPlugin);
50 | client.start();
51 |
52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
53 | // Hence we run if after all native modules have been initialized
54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
55 | if (reactContext == null) {
56 | reactInstanceManager.addReactInstanceEventListener(
57 | new ReactInstanceEventListener() {
58 | @Override
59 | public void onReactContextInitialized(ReactContext reactContext) {
60 | reactInstanceManager.removeReactInstanceEventListener(this);
61 | reactContext.runOnNativeModulesQueueThread(
62 | new Runnable() {
63 | @Override
64 | public void run() {
65 | client.addPlugin(new FrescoFlipperPlugin());
66 | }
67 | });
68 | }
69 | });
70 | } else {
71 | client.addPlugin(new FrescoFlipperPlugin());
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Example/App.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | import React from 'react';
9 | import type { PropsWithChildren } from 'react';
10 | import {
11 | Image,
12 | SafeAreaView,
13 | ScrollView,
14 | StatusBar,
15 | StyleSheet,
16 | Text,
17 | useColorScheme,
18 | View,
19 | } from 'react-native';
20 |
21 | import {
22 | Colors,
23 | DebugInstructions,
24 | Header,
25 | LearnMoreLinks,
26 | ReloadInstructions,
27 | } from 'react-native/Libraries/NewAppScreen';
28 | import Animated, {
29 | useAnimatedStyle,
30 | useSharedValue,
31 | } from 'react-native-reanimated';
32 | import esbuildLogoSource from './esbuild-logo.png';
33 | import 'react-native-get-random-values';
34 | import { nanoid } from 'nanoid';
35 |
36 | type SectionProps = PropsWithChildren<{
37 | title: string;
38 | }>;
39 |
40 | function Section({ children, title }: SectionProps): JSX.Element {
41 | const isDarkMode = useColorScheme() === 'dark';
42 | return (
43 |
44 |
52 | {title}
53 |
54 |
62 | {children}
63 |
64 |
65 | );
66 | }
67 |
68 | function App(): JSX.Element {
69 | const isDarkMode = useColorScheme() === 'dark';
70 |
71 | const backgroundStyle = {
72 | backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
73 | };
74 |
75 | console.warn('A warning that should be symbolicated', nanoid());
76 |
77 | const pressed = useSharedValue(false);
78 | const uas = useAnimatedStyle(() => {
79 | return {
80 | backgroundColor: pressed.value ? '#FEEF86' : '#001972',
81 | transform: [{ scale: pressed.value ? 1.2 : 1 }],
82 | };
83 | });
84 |
85 | return (
86 |
87 |
91 |
95 |
96 |
101 |
102 |
103 |
104 | Edit App.tsx to change this
105 | screen and then come back to see your edits.
106 |
107 |
110 |
113 |
114 | Read the docs to discover what to do next:
115 |
116 |
117 |
118 |
119 |
120 | );
121 | }
122 |
123 | const styles = StyleSheet.create({
124 | sectionContainer: {
125 | marginTop: 32,
126 | paddingHorizontal: 24,
127 | },
128 | sectionTitle: {
129 | fontSize: 24,
130 | fontWeight: '600',
131 | },
132 | sectionDescription: {
133 | marginTop: 8,
134 | fontSize: 18,
135 | fontWeight: '400',
136 | },
137 | highlight: {
138 | fontWeight: '700',
139 | },
140 | esbuildLogo: {
141 | position: 'absolute',
142 | top: 10,
143 | left: 10,
144 | },
145 | animatedBall: {
146 | position: 'absolute',
147 | top: 10,
148 | right: 10,
149 | borderRadius: 20,
150 | width: 40,
151 | height: 40,
152 | },
153 | });
154 |
155 | export default App;
156 |
--------------------------------------------------------------------------------
/Example/ios/Example/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/commands/start.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const path = require('path');
3 | const { parse: parseUrl } = require('url');
4 | const {
5 | createDevServerMiddleware,
6 | indexPageMiddleware,
7 | } = require('@react-native-community/cli-server-api');
8 | const chalk = require('chalk');
9 | const {
10 | createBundler,
11 | serveAsset,
12 | extractBundleParams,
13 | symbolicateStack,
14 | enableInteractiveMode,
15 | createHMREndpoint,
16 | } = require('../server');
17 | const { emptyDefaultCacheDir } = require('../cache');
18 | const { defaultLogger } = require('../logger');
19 | const { ASSETS_PUBLIC_PATH } = require('../config');
20 |
21 | module.exports = (getBundleConfig) => async (_, config, args) => {
22 | // Hermes for some reason hijacks this upon import and messes with stack traces
23 | process.removeAllListeners('uncaughtException');
24 | process.removeAllListeners('unhandledRejection');
25 |
26 | const {
27 | host = '127.0.0.1',
28 | port = 8081,
29 | projectRoot = config.root,
30 | resetCache,
31 | interactive,
32 | } = args;
33 |
34 | if (resetCache) {
35 | emptyDefaultCacheDir();
36 | }
37 |
38 | const { middleware, websocketEndpoints, messageSocketEndpoint } =
39 | createDevServerMiddleware({
40 | host,
41 | port,
42 | watchFolders: [],
43 | });
44 |
45 | const hmr = createHMREndpoint(defaultLogger);
46 |
47 | const bundler = createBundler(
48 | (options) => getBundleConfig(config, options),
49 | hmr.reload,
50 | defaultLogger
51 | );
52 |
53 | middleware.use(async (req, res, next) => {
54 | try {
55 | const { pathname, query } = parseUrl(req.url, true);
56 | if (pathname.startsWith(ASSETS_PUBLIC_PATH)) {
57 | const requestPath = path.join(
58 | config.root,
59 | pathname.substring(ASSETS_PUBLIC_PATH.length)
60 | );
61 | const { platform } = query;
62 |
63 | if (!(await serveAsset(res, requestPath, platform))) {
64 | next();
65 | }
66 | } else if (pathname.endsWith('.bundle')) {
67 | const { platform, dev, minify, entryFile } = extractBundleParams(
68 | req.url
69 | );
70 | try {
71 | const bundle = await bundler.getBundle(
72 | platform,
73 | path.join(projectRoot, entryFile),
74 | dev,
75 | minify
76 | );
77 | return res
78 | .writeHead(200, { 'Content-Type': 'application/javascript' })
79 | .end(bundle);
80 | } catch (error) {
81 | return res.writeHead(400).end(error.message);
82 | }
83 | } else if (pathname === '/symbolicate') {
84 | const { stack } = JSON.parse(req.rawBody);
85 | const url = stack.find(
86 | ({ file }) => file && file.startsWith('http')
87 | ).file;
88 | const { platform, entryFile } = extractBundleParams(url);
89 | const sourceMapConsumer = await bundler.getSourcemap(
90 | platform,
91 | path.join(projectRoot, entryFile)
92 | );
93 |
94 | const symbolicated = symbolicateStack(sourceMapConsumer, stack);
95 |
96 | const stringified = JSON.stringify(symbolicated);
97 | return res
98 | .writeHead(200, { 'Content-Type': 'application/json' })
99 | .end(stringified);
100 | }
101 | } catch (error) {
102 | return next(error);
103 | }
104 | next();
105 | });
106 |
107 | middleware.use(indexPageMiddleware);
108 |
109 | const server = http.createServer(middleware);
110 |
111 | server.on('upgrade', (request, socket, head) => {
112 | const { pathname } = parseUrl(request.url);
113 | const handler =
114 | pathname === '/hot' ? hmr.server : websocketEndpoints[pathname];
115 | if (handler) {
116 | handler.handleUpgrade(request, socket, head, (ws) => {
117 | handler.emit('connection', ws, request);
118 | });
119 | } else {
120 | socket.destroy();
121 | }
122 | });
123 |
124 | server.listen(port);
125 |
126 | const LOGO = chalk.bgHex('#FFCF00').hex('#000000')('»');
127 | console.log(`${LOGO} esbuild listening on http://${host}:${port}\n`);
128 |
129 | if (interactive) {
130 | enableInteractiveMode(messageSocketEndpoint);
131 | }
132 | };
133 |
--------------------------------------------------------------------------------
/src/server/bundler.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const esbuild = require('esbuild');
3 | const { SourceMapConsumer } = require('source-map');
4 | const { formatFilePath } = require('../logger');
5 | const chalk = require('chalk');
6 |
7 | function createBundler(getBundleConfig, onBuild, logger) {
8 | const promiseMap = {};
9 | const outputMap = {};
10 | const sourceMap = {};
11 |
12 | const getBundleOutputPath = (platform, entryFile) =>
13 | `${entryFile.substring(
14 | 0,
15 | entryFile.length - path.extname(entryFile).length
16 | )}.${platform}.js`;
17 |
18 | const getBundle = async (
19 | platform,
20 | entryFile = 'index',
21 | dev = true,
22 | minify = false
23 | ) => {
24 | const bundleOutput = getBundleOutputPath(platform, entryFile);
25 | if (!promiseMap[bundleOutput]) {
26 | let buildResolver = null;
27 | let buildRejecter = null;
28 | let buildStart = -1;
29 |
30 | const setupBuildPromise = () => {
31 | const promise = new Promise((resolve, reject) => {
32 | buildResolver = resolve;
33 | buildRejecter = reject;
34 | });
35 | buildStart = Date.now();
36 | // Rejections are generally caught and forwarded to the app
37 | // but rebuilds aren't being awaited instantly and we don't
38 | // want to kill the process in those cases.
39 | promise.catch(() => null);
40 | promiseMap[bundleOutput] = promise;
41 | };
42 | setupBuildPromise();
43 |
44 | const buildStatusPlugin = {
45 | name: 'build-status',
46 | setup(build) {
47 | let localPath = path.relative(
48 | build.initialOptions.sourceRoot,
49 | entryFile
50 | );
51 |
52 | build.onStart(async () => {
53 | if (!buildResolver) {
54 | setupBuildPromise();
55 | }
56 | const resolved = await build.resolve(
57 | entryFile.startsWith('/') ? entryFile : `./${localPath}`,
58 | {
59 | kind: 'entry-point',
60 | resolveDir: build.initialOptions.sourceRoot,
61 | }
62 | );
63 | if (resolved.errors.length === 0) {
64 | localPath = path.relative(
65 | build.initialOptions.sourceRoot,
66 | resolved.path
67 | );
68 | }
69 | logger.warn(
70 | 'BUNDLE',
71 | `${formatFilePath(localPath)}: ${chalk.dim(
72 | `${platform} building...`
73 | )}`
74 | );
75 | });
76 |
77 | build.onEnd((result) => {
78 | const { errors, outputFiles } = result;
79 | outputMap[bundleOutput] = outputFiles;
80 | sourceMap[bundleOutput] = null;
81 | if (errors.length === 0) {
82 | logger.success(
83 | 'BUNDLE',
84 | `${formatFilePath(localPath)}: ${chalk.dim(
85 | `${platform} build completed in ${Date.now() - buildStart}ms`
86 | )}`
87 | );
88 | const file = outputFiles.find((f) => f.path === bundleOutput);
89 | buildResolver(file.contents);
90 | if (onBuild) {
91 | onBuild(result);
92 | }
93 | } else {
94 | logger.error(
95 | 'BUNDLE',
96 | `${formatFilePath(localPath)}: ${chalk.bold.red(
97 | `${platform} build failed, see errors above`
98 | )}`
99 | );
100 | buildRejecter(
101 | new Error(`Compilation failed with "${errors[0].text}"`)
102 | );
103 | }
104 | buildResolver = null;
105 | buildRejecter = null;
106 | });
107 | },
108 | };
109 |
110 | const buildOptions = getBundleConfig({
111 | platform,
112 | dev,
113 | minify,
114 | entryFile,
115 | bundleOutput,
116 | sourcemapOutput: `${bundleOutput}.map`,
117 | });
118 |
119 | const ctx = await esbuild.context({
120 | ...buildOptions,
121 | bundle: true,
122 | write: false,
123 | plugins: (buildOptions.plugins || []).concat(buildStatusPlugin),
124 | });
125 | await ctx.watch();
126 | }
127 | return promiseMap[bundleOutput];
128 | };
129 |
130 | const getSourcemap = async (platform, entryFile) => {
131 | const bundleOutput = getBundleOutputPath(platform, entryFile);
132 | if (!sourceMap[bundleOutput]) {
133 | const sourcemapOutput = `${bundleOutput}.map`;
134 | const outputFiles = outputMap[bundleOutput];
135 | if (!outputFiles) {
136 | throw new Error(
137 | `No output files found for ${bundleOutput}, ensure compilation has finished`
138 | );
139 | }
140 | const file = outputFiles.find((f) => f.path === sourcemapOutput);
141 | const sourcemap = Buffer.from(file.contents).toString('utf8');
142 | sourceMap[bundleOutput] = new SourceMapConsumer(sourcemap);
143 | }
144 | return sourceMap[bundleOutput];
145 | };
146 |
147 | return { getBundle, getSourcemap };
148 | }
149 |
150 | module.exports = { createBundler };
151 |
--------------------------------------------------------------------------------
/src/plugins/syntax-aware-loader.js:
--------------------------------------------------------------------------------
1 | const crypto = require('crypto');
2 | const fs = require('fs');
3 | const path = require('path');
4 |
5 | const babel = require('@babel/core');
6 | const { outputFile } = require('fs-extra');
7 | const { getDefaultCacheDir } = require('../cache');
8 |
9 | const md5 = (string) => crypto.createHash('md5').update(string).digest('hex');
10 |
11 | const defaultHasFlowSyntax = (contents, filePath) =>
12 | path.extname(filePath) === '.js' &&
13 | (contents.includes('@flow') ||
14 | contents.includes('@noflow') ||
15 | filePath.includes(
16 | `node_modules/react-native/Libraries/NativeComponent/NativeComponentRegistryUnstable.js`
17 | ));
18 |
19 | const defaultHasReanimatedSyntax = (contents, filePath) =>
20 | [
21 | 'createAnimatedPropAdapter',
22 | 'useAnimatedGestureHandler',
23 | 'useAnimatedProps',
24 | 'useAnimatedReaction',
25 | 'useAnimatedScrollHandler',
26 | 'useAnimatedStyle',
27 | 'useDerivedValue',
28 | 'useWorkletCallback',
29 | 'withDecay',
30 | 'withRepeat',
31 | 'withSpring',
32 | 'withTiming',
33 | "'worklet'",
34 | '"worklet"',
35 | ].find((fn) => contents.includes(fn));
36 |
37 | const syntaxAwareLoaderPlugin = (options = {}) => ({
38 | name: 'syntax-aware-loader',
39 | setup(build, { transform } = {}) {
40 | const {
41 | filter = /.*/,
42 | hasFlowSyntax = defaultHasFlowSyntax,
43 | hasReanimatedSyntax = defaultHasReanimatedSyntax,
44 | namespace = '',
45 | cache = true,
46 | } = options;
47 | const transformCache = new Map();
48 |
49 | const loaderMap = build.initialOptions.loader || {};
50 | const getLoader = (extension) => {
51 | if (loaderMap[extension]) {
52 | return loaderMap[extension];
53 | }
54 | switch (extension) {
55 | case '.ts':
56 | return 'ts';
57 | case '.tsx':
58 | return 'tsx';
59 | default:
60 | return 'js';
61 | }
62 | };
63 |
64 | const transformContents = async (args, contents, config) => {
65 | const babelOptions = babel.loadOptions({
66 | minified: false,
67 | compact: false,
68 | ...config,
69 | sourceMaps: 'inline',
70 | filename: args.path,
71 | caller: {
72 | name: 'esbuild-plugin-syntax-aware-loader',
73 | supportsStaticESM: true,
74 | },
75 | });
76 | if (!babelOptions) {
77 | return { contents };
78 | }
79 |
80 | if (babelOptions.sourceMaps) {
81 | const filename = path.relative(process.cwd(), args.path);
82 |
83 | babelOptions.sourceFileName = filename;
84 | }
85 |
86 | const transformWithBabel = () =>
87 | new Promise((resolve, reject) => {
88 | babel.transform(contents, babelOptions, (error, result) => {
89 | if (error) {
90 | reject(error);
91 | } else {
92 | resolve(result.code);
93 | }
94 | });
95 | });
96 |
97 | if (cache) {
98 | const cachePath = path.join(
99 | typeof cache === 'string' ? cache : getDefaultCacheDir(),
100 | md5(JSON.stringify(babelOptions) + contents)
101 | );
102 | try {
103 | return await fs.promises.readFile(cachePath, { encoding: 'utf8' });
104 | } catch (err) {
105 | const transformed = await transformWithBabel();
106 | await outputFile(cachePath, transformed);
107 | return transformed;
108 | }
109 | }
110 | return transformWithBabel();
111 | };
112 |
113 | const stripFlow = (args, contents) =>
114 | transformContents(args, contents, {
115 | babelrc: false,
116 | configFile: false,
117 | plugins: [
118 | '@babel/plugin-syntax-flow',
119 | '@babel/plugin-transform-flow-strip-types',
120 | '@babel/plugin-syntax-jsx',
121 | ],
122 | });
123 |
124 | const fullBabelTransform = (args, contents) =>
125 | transformContents(args, contents, {});
126 |
127 | build.onLoad({ filter, namespace }, async (args) => {
128 | let handle;
129 | try {
130 | handle = await fs.promises.open(args.path, 'r');
131 | let entry = transformCache.get(args.path);
132 | const stats = await handle.stat();
133 |
134 | // Use in-memory cache unless file was modified.
135 | // Ideally we'd compare file contents, but it would be
136 | // slower and is already done by the file system cache
137 | if (!entry || entry.mtimeMs !== stats.mtimeMs) {
138 | let contents = await handle.readFile('utf8');
139 | let loader = getLoader(path.extname(args.path));
140 |
141 | if (hasReanimatedSyntax(contents, args.path)) {
142 | contents = await fullBabelTransform(args, contents);
143 | loader = 'js';
144 | } else if (hasFlowSyntax(contents, args.path)) {
145 | contents = await stripFlow(args, contents);
146 | }
147 |
148 | entry = {
149 | transformed: contents,
150 | loader,
151 | mtimeMs: stats.mtimeMs,
152 | };
153 |
154 | if (cache) {
155 | transformCache.set(args.path, entry);
156 | }
157 | }
158 |
159 | return { contents: entry.transformed, loader: entry.loader };
160 | } finally {
161 | if (handle) {
162 | handle.close();
163 | }
164 | }
165 | });
166 | },
167 | });
168 |
169 | module.exports = {
170 | syntaxAwareLoaderPlugin,
171 | defaultHasFlowSyntax,
172 | defaultHasReanimatedSyntax,
173 | };
174 |
--------------------------------------------------------------------------------
/src/plugins/asset-loader.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs-extra');
2 | const path = require('path');
3 | const crypto = require('crypto');
4 | const { promisify } = require('util');
5 | const imageSize = require('image-size');
6 | const sizeOf = promisify(imageSize);
7 | const { getAssetDestinationPath } = require('./asset-destination');
8 | const { ASSETS_PUBLIC_PATH } = require('../config');
9 |
10 | function escapeRegex(string) {
11 | return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
12 | }
13 |
14 | async function getFilesHash(files) {
15 | const hash = crypto.createHash('md5');
16 | for (const file of files) {
17 | hash.update(await fs.readFile(file));
18 | }
19 | return hash.digest('hex');
20 | }
21 |
22 | function getAssetType(extension) {
23 | switch (extension) {
24 | case '.jpeg':
25 | return 'jpg';
26 | case '.tif':
27 | return 'tiff';
28 | default:
29 | return extension.slice(1);
30 | }
31 | }
32 |
33 | const assetLoaderPlugin = ({
34 | extensions,
35 | scalableExtensions,
36 | platform,
37 | rootdir,
38 | outdir,
39 | dev = false,
40 | publicPath = ASSETS_PUBLIC_PATH,
41 | assetRegistryPath = '@react-native/assets-registry/registry.js',
42 | } = {}) => ({
43 | name: 'react-native-asset-loader',
44 | setup(build) {
45 | const filter = new RegExp(`(${extensions.map(escapeRegex).join('|')})$`);
46 | const assets = [];
47 | const dirCache = new Map();
48 | const priority = (queryPlatform) =>
49 | ['native', platform].indexOf(queryPlatform);
50 |
51 | const resolveWithSuffix = async (args, suffix) => {
52 | const extension = path.extname(args.path);
53 | const basename = args.path.substr(0, args.path.length - extension.length);
54 | return build.resolve(`${basename}${suffix}${extension}`, {
55 | resolveDir: args.resolveDir,
56 | importer: args.importer,
57 | kind: args.kind,
58 | namespace: args.namespace,
59 | pluginData: { skipReactNativeAssetLoader: true },
60 | });
61 | };
62 |
63 | const resolveBaseScale = async (args) => {
64 | const suffixlessResult = await resolveWithSuffix(args, '');
65 | if (suffixlessResult.errors.length !== 0) {
66 | const result = await resolveWithSuffix(args, '@1x');
67 | if (result.errors.length === 0) {
68 | return result;
69 | }
70 | }
71 | return suffixlessResult;
72 | };
73 |
74 | build.onResolve({ filter }, async (args) => {
75 | if (
76 | args.pluginData &&
77 | args.pluginData.skipReactNativeAssetLoader === true
78 | ) {
79 | // Avoid recursive calls
80 | return null;
81 | }
82 |
83 | const result = await resolveBaseScale(args);
84 | if (result.errors.length > 0) {
85 | return { errors: result.errors };
86 | }
87 |
88 | return { path: result.path, namespace: 'react-native-asset' };
89 | });
90 |
91 | build.onLoad(
92 | { filter: /./, namespace: 'react-native-asset' },
93 | async (args) => {
94 | const dirPath = path.dirname(args.path);
95 | const extension = path.extname(args.path);
96 | const relativePath = path.relative(rootdir, args.path);
97 |
98 | const suffix = `(@(\\d+(\\.\\d+)?)x)?(\\.(${platform}|native))?${escapeRegex(
99 | extension
100 | )}$`;
101 | const basename = path
102 | .basename(args.path)
103 | .replace(new RegExp(suffix), '');
104 | if (!dirCache.has(dirPath)) {
105 | dirCache.set(dirPath, await fs.readdir(dirPath));
106 | }
107 | const files = dirCache.get(dirPath);
108 | const pattern = scalableExtensions.includes(extension)
109 | ? new RegExp(`^${escapeRegex(basename)}${suffix}`)
110 | : new RegExp(
111 | `^${escapeRegex(basename)}(\\.(${platform}|native))?${escapeRegex(
112 | extension
113 | )}$`
114 | );
115 | const scales = {};
116 | let found = false;
117 | for (const file of files) {
118 | const match = pattern.exec(file);
119 | if (match) {
120 | let [, , scale, , , platformExtension] = match;
121 | scale = scale || '1';
122 | if (
123 | !scales[scale] ||
124 | priority(platformExtension) > priority(scales[scale].platform)
125 | ) {
126 | scales[scale] = { platform: platformExtension, name: file };
127 | found = true;
128 | }
129 | }
130 | }
131 | if (!found) {
132 | throw new Error(`Unable to resolve "${args.path}"`);
133 | }
134 | const httpServerLocation = path.join(
135 | publicPath,
136 | path.dirname(relativePath)
137 | );
138 | assets.push({
139 | relativePath,
140 | basename,
141 | extension,
142 | scales,
143 | httpServerLocation,
144 | });
145 | const baseScale = scales['1'];
146 | if (!baseScale) {
147 | throw new Error(`Base scale not found for "${relativePath}"`);
148 | }
149 | const assetType = getAssetType(extension);
150 | const dimensions = imageSize.types.includes(assetType)
151 | ? await sizeOf(path.join(dirPath, baseScale.name))
152 | : {};
153 | const hash = await getFilesHash(
154 | Object.values(scales)
155 | .map((scale) => path.join(dirPath, scale.name))
156 | .sort()
157 | );
158 |
159 | return {
160 | contents: `module.exports = require('${assetRegistryPath}').registerAsset(${JSON.stringify(
161 | {
162 | __packager_asset: true,
163 | scales: Object.keys(scales)
164 | .map((scale) => Number.parseFloat(scale))
165 | .sort(),
166 | name: basename,
167 | type: extension.substr(1),
168 | hash,
169 | httpServerLocation,
170 | fileSystemLocation: dev ? path.dirname(relativePath) : undefined,
171 | height: dimensions.height,
172 | width: dimensions.width,
173 | }
174 | )})`,
175 | loader: 'js',
176 | resolveDir: dirPath,
177 | };
178 | }
179 | );
180 |
181 | if (outdir) {
182 | build.onEnd(() => {
183 | assets.map(async (asset) => {
184 | const { scales, relativePath } = asset;
185 | const sourceDir = path.dirname(path.join(rootdir, relativePath));
186 | return Promise.all(
187 | Object.entries(scales).map(async ([scale, { name }]) => {
188 | const source = path.join(sourceDir, name);
189 | const destination = path.join(
190 | outdir,
191 | getAssetDestinationPath(asset, scale, platform)
192 | );
193 | await fs.mkdir(path.dirname(destination), {
194 | recursive: true,
195 | });
196 | await fs.copy(source, destination);
197 | })
198 | );
199 | });
200 | });
201 | }
202 | },
203 | });
204 |
205 | module.exports = { assetLoaderPlugin };
206 |
--------------------------------------------------------------------------------
/Example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 | apply plugin: "com.facebook.react"
3 |
4 | import com.android.build.OutputFile
5 |
6 | /**
7 | * This is the configuration block to customize your React Native Android app.
8 | * By default you don't need to apply any configuration, just uncomment the lines you need.
9 | */
10 | react {
11 | /* Folders */
12 | // The root of your project, i.e. where "package.json" lives. Default is '..'
13 | // root = file("../")
14 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native
15 | // reactNativeDir = file("../node_modules/react-native")
16 | // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen
17 | // codegenDir = file("../node_modules/react-native-codegen")
18 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
19 | // cliFile = file("../node_modules/react-native/cli.js")
20 |
21 | /* Variants */
22 | // The list of variants to that are debuggable. For those we're going to
23 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
24 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
25 | // debuggableVariants = ["liteDebug", "prodDebug"]
26 |
27 | /* Bundling */
28 | // A list containing the node command and its flags. Default is just 'node'.
29 | // nodeExecutableAndArgs = ["node"]
30 | //
31 | // The command to run when bundling. By default is 'bundle'
32 | bundleCommand = "esbuild-bundle"
33 |
34 | // The path to the CLI configuration file. Default is empty.
35 | // bundleConfig = file(../rn-cli.config.js)
36 | //
37 | // The name of the generated asset file containing your JS bundle
38 | // bundleAssetName = "MyApplication.android.bundle"
39 | //
40 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
41 | // entryFile = file("../js/MyApplication.android.js")
42 | //
43 | // A list of extra flags to pass to the 'bundle' commands.
44 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
45 | // extraPackagerArgs = []
46 |
47 | /* Hermes Commands */
48 | // The hermes compiler command to run. By default it is 'hermesc'
49 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
50 | //
51 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
52 | // hermesFlags = ["-O", "-output-source-map"]
53 | }
54 |
55 | /**
56 | * Set this to true to create four separate APKs instead of one,
57 | * one for each native architecture. This is useful if you don't
58 | * use App Bundles (https://developer.android.com/guide/app-bundle/)
59 | * and want to have separate APKs to upload to the Play Store.
60 | */
61 | def enableSeparateBuildPerCPUArchitecture = false
62 |
63 | /**
64 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
65 | */
66 | def enableProguardInReleaseBuilds = false
67 |
68 | /**
69 | * The preferred build flavor of JavaScriptCore (JSC)
70 | *
71 | * For example, to use the international variant, you can use:
72 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
73 | *
74 | * The international variant includes ICU i18n library and necessary data
75 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
76 | * give correct results when using with locales other than en-US. Note that
77 | * this variant is about 6MiB larger per architecture than default.
78 | */
79 | def jscFlavor = 'org.webkit:android-jsc:+'
80 |
81 | /**
82 | * Private function to get the list of Native Architectures you want to build.
83 | * This reads the value from reactNativeArchitectures in your gradle.properties
84 | * file and works together with the --active-arch-only flag of react-native run-android.
85 | */
86 | def reactNativeArchitectures() {
87 | def value = project.getProperties().get("reactNativeArchitectures")
88 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
89 | }
90 |
91 | android {
92 | ndkVersion rootProject.ext.ndkVersion
93 |
94 | compileSdkVersion rootProject.ext.compileSdkVersion
95 |
96 | namespace "com.example"
97 | defaultConfig {
98 | applicationId "com.example"
99 | minSdkVersion rootProject.ext.minSdkVersion
100 | targetSdkVersion rootProject.ext.targetSdkVersion
101 | versionCode 1
102 | versionName "1.0"
103 | }
104 |
105 | splits {
106 | abi {
107 | reset()
108 | enable enableSeparateBuildPerCPUArchitecture
109 | universalApk false // If true, also generate a universal APK
110 | include (*reactNativeArchitectures())
111 | }
112 | }
113 | signingConfigs {
114 | debug {
115 | storeFile file('debug.keystore')
116 | storePassword 'android'
117 | keyAlias 'androiddebugkey'
118 | keyPassword 'android'
119 | }
120 | }
121 | buildTypes {
122 | debug {
123 | signingConfig signingConfigs.debug
124 | }
125 | release {
126 | // Caution! In production, you need to generate your own keystore file.
127 | // see https://reactnative.dev/docs/signed-apk-android.
128 | signingConfig signingConfigs.debug
129 | minifyEnabled enableProguardInReleaseBuilds
130 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
131 | }
132 | }
133 |
134 | // applicationVariants are e.g. debug, release
135 | applicationVariants.all { variant ->
136 | variant.outputs.each { output ->
137 | // For each separate APK per architecture, set a unique version code as described here:
138 | // https://developer.android.com/studio/build/configure-apk-splits.html
139 | // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
140 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
141 | def abi = output.getFilter(OutputFile.ABI)
142 | if (abi != null) { // null for the universal-debug, universal-release variants
143 | output.versionCodeOverride =
144 | defaultConfig.versionCode * 1000 + versionCodes.get(abi)
145 | }
146 |
147 | }
148 | }
149 | }
150 |
151 | dependencies {
152 | // The version of react-native is set by the React Native Gradle Plugin
153 | implementation("com.facebook.react:react-android")
154 |
155 | implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0")
156 |
157 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
158 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
159 | exclude group:'com.squareup.okhttp3', module:'okhttp'
160 | }
161 |
162 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
163 | if (hermesEnabled.toBoolean()) {
164 | implementation("com.facebook.react:hermes-android")
165 | } else {
166 | implementation jscFlavor
167 | }
168 | }
169 |
170 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
171 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
react-native-esbuild
2 | The fastest bundler for React Native.
3 |
4 |
13 |
14 | ## Features
15 |
16 | - **Fast** – ~10-50x faster depending on project
17 | - **Tree shaking** – Smaller bundles means faster apps (**21% smaller** for `init` project)
18 | - **Compatible** – Drop-in replacement for metro
19 | - **Configurable** – Support for custom transformers and env variables
20 |
21 | ## Sponsoring
22 |
23 | If this library helped you, please consider [sponsoring](https://github.com/sponsors/oblador).
24 |
25 | ## Installation
26 |
27 | ```shell
28 | yarn add react-native-esbuild esbuild
29 | ```
30 |
31 | ## Configuration
32 |
33 | ### `react-native` CLI plugin
34 |
35 | Make sure `react-native.config.js` exists in the root of your project, and create one if not. Add this library to the `commands` section like this:
36 |
37 | ```js
38 | // react-native.config.js
39 | const { commands } = require('react-native-esbuild');
40 |
41 | module.exports = {
42 | commands,
43 | };
44 | ```
45 |
46 | ### Optional: Esbuild settings
47 |
48 | If you want to customize the [esbuild configuration](https://esbuild.github.io/api/#simple-options), for example by adding your own plugins you may do so with the `createEsbuildCommands` function:
49 |
50 | ```js
51 | // react-native.config.js
52 | const { createEsbuildCommands, babelPlugin } = require('react-native-esbuild');
53 |
54 | // See https://esbuild.github.io/api/#simple-options
55 | const commands = createEsbuildCommands((config) => ({
56 | ...config,
57 | plugins: config.plugins.concat(
58 | babelPlugin({
59 | filter: /src\/my-babel-components\/.+\.[tj]sx?$/,
60 | })
61 | ),
62 | }));
63 |
64 | module.exports = {
65 | commands,
66 | };
67 | ```
68 |
69 | ### Optional: Use esbuild for development
70 |
71 | 1. Open `package.json` in your editor and locate `scripts` section.
72 | 2. Edit `start` script to be `react-native esbuild-start`.
73 | 3. Prevent metro from starting automatically by appending `--no-packager` to the `ios`/`android` scripts.
74 |
75 | ```json
76 | {
77 | "scripts": {
78 | "android": "react-native run-android --no-packager",
79 | "ios": "react-native run-ios --no-packager",
80 | "start": "react-native esbuild-start"
81 | }
82 | }
83 | ```
84 |
85 | ### Optional: Build production app with esbuild
86 |
87 | #### Android
88 |
89 | Set `project.ext.react.bundleCommand` to `esbuild-bundle` in `android/app/build.gradle`:
90 |
91 | ```gradle
92 | // android/app/build.gradle
93 | project.ext.react = [
94 | enableHermes: false,
95 | bundleCommand: "esbuild-bundle",
96 | ]
97 | ```
98 |
99 | #### iOS
100 |
101 | 1. Open your iOS project in Xcode manually or with `xed ios`
102 | 2. Select the `Build Phases` tab in your project settings.
103 | 3. Expand the `Bundle React Native code and images` section and add `export BUNDLE_COMMAND=esbuild-bundle` so it looks like this:
104 |
105 | ```shell
106 | set -e
107 |
108 | export BUNDLE_COMMAND=esbuild-bundle
109 | export NODE_BINARY=node
110 | ../node_modules/react-native/scripts/react-native-xcode.sh
111 | ```
112 |
113 | ## Usage
114 |
115 | This library aims to be a plug-in replacement for the metro equivalent commands with the `esbuild-` prefix.
116 |
117 | ### `react-native esbuild-start`
118 |
119 | | **Argument** | **Description** | **Default** |
120 | | ------------------ | -------------------------------- | ----------- |
121 | | `--port` | Port to listen for http requests | `8081` |
122 | | `--host` | Host to listen for http requests | `127.0.0.1` |
123 | | `--projectRoot` | Path to a custom project root. | _None_ |
124 | | `--reset-cache` | Removes cached files. | _N/A_ |
125 | | `--no-interactive` | Disables interactive mode. | `false` |
126 |
127 | ### `react-native esbuild-bundle`
128 |
129 | | **Argument** | **Description** | **Default** |
130 | | -------------------- | --------------------------------------------------------------------------------- | ----------------- |
131 | | `--entry-file` | Path to the root JS file, either absolute or relative to JS root | `index.js` |
132 | | `--platform` | Either `ios` or `android` | `ios` |
133 | | `--dev` | If `false`, warnings are disabled and the bundle is minified | `true` |
134 | | `--minify` | Allows overriding whether bundle is minified otherwise determined by `dev` value. | Opposite of `dev` |
135 | | `--bundle-output` | File name where to store the resulting bundle. | _None_ |
136 | | `--sourcemap-output` | File name where to store the sourcemap file for resulting bundle. | _None_ |
137 | | `--assets-dest` | Directory name where to store assets referenced in the bundle. | _None_ |
138 | | `--reset-cache` | Removes cached files. | _N/A_ |
139 |
140 | ## Troubleshooting
141 |
142 | ### Flow syntax errors such as `Expected "from" but found "{"`
143 |
144 | Esbuild doesn't natively support flow so such syntax needs to be stripped with a plugin. By default any file with `@flow` or `@noflow` pragmas will be stripped from flow, but you may also opt-in to flow stripping for more files by passing a custom flow syntax checker:
145 |
146 | ```js
147 | // react-native.config.js
148 | const {
149 | createEsbuildCommands,
150 | defaultHasFlowSyntax,
151 | syntaxAwareLoaderPlugin,
152 | } = require('react-native-esbuild');
153 |
154 | const FLOW_MODULES_WITHOUT_PRAGMA = ['react-native-video', 'rn-fetch-blob'];
155 |
156 | const commands = createEsbuildCommands((config, args) => ({
157 | ...config,
158 | plugins: config.plugins
159 | .filter((plugin) => plugin.name !== 'syntax-aware-loader')
160 | .concat(
161 | syntaxAwareLoaderPlugin({
162 | filter: /\.([mc]js|[tj]sx?)$/,
163 | cache: args.dev,
164 | hasFlowSyntax: (contents, filePath) =>
165 | defaultHasFlowSyntax(contents, filePath) ||
166 | FLOW_MODULES_WITHOUT_PRAGMA.find((m) =>
167 | filePath.includes(`node_modules/${m}/`)
168 | ),
169 | })
170 | ),
171 | }));
172 |
173 | module.exports = {
174 | commands,
175 | };
176 | ```
177 |
178 | ## Limitations
179 |
180 | ### Hermes engine
181 |
182 | Hermes doesn't support crucial ES6 features like block level scoping (`let`/`const`) and the team doesn't seem to want to merge this feature mentioning it [being a too big of a change](https://github.com/facebook/hermes/issues/575#issuecomment-902169154) without [having good enough reasons to add it](https://github.com/facebook/hermes/issues/715#issuecomment-1083236894).
183 |
184 | ### HMR/Fast Refresh
185 |
186 | Esbuild [doesn't support Fast Refresh or Hot Module Replacement](https://github.com/evanw/esbuild/issues/151#issuecomment-634441809), but this library supports live reload instead.
187 |
188 | ## License
189 |
190 | MIT © Joel Arvidsson 2022-
191 |
--------------------------------------------------------------------------------
/Example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | #
21 | # Gradle start up script for POSIX generated by Gradle.
22 | #
23 | # Important for running:
24 | #
25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
26 | # noncompliant, but you have some other compliant shell such as ksh or
27 | # bash, then to run this script, type that shell name before the whole
28 | # command line, like:
29 | #
30 | # ksh Gradle
31 | #
32 | # Busybox and similar reduced shells will NOT work, because this script
33 | # requires all of these POSIX shell features:
34 | # * functions;
35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
37 | # * compound commands having a testable exit status, especially «case»;
38 | # * various built-in commands including «command», «set», and «ulimit».
39 | #
40 | # Important for patching:
41 | #
42 | # (2) This script targets any POSIX shell, so it avoids extensions provided
43 | # by Bash, Ksh, etc; in particular arrays are avoided.
44 | #
45 | # The "traditional" practice of packing multiple parameters into a
46 | # space-separated string is a well documented source of bugs and security
47 | # problems, so this is (mostly) avoided, by progressively accumulating
48 | # options in "$@", and eventually passing that to Java.
49 | #
50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
52 | # see the in-line comments for details.
53 | #
54 | # There are tweaks for specific operating systems such as AIX, CygWin,
55 | # Darwin, MinGW, and NonStop.
56 | #
57 | # (3) This script is generated from the Groovy template
58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
59 | # within the Gradle project.
60 | #
61 | # You can find Gradle at https://github.com/gradle/gradle/.
62 | #
63 | ##############################################################################
64 |
65 | # Attempt to set APP_HOME
66 |
67 | # Resolve links: $0 may be a link
68 | app_path=$0
69 |
70 | # Need this for daisy-chained symlinks.
71 | while
72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
73 | [ -h "$app_path" ]
74 | do
75 | ls=$( ls -ld "$app_path" )
76 | link=${ls#*' -> '}
77 | case $link in #(
78 | /*) app_path=$link ;; #(
79 | *) app_path=$APP_HOME$link ;;
80 | esac
81 | done
82 |
83 | # This is normally unused
84 | # shellcheck disable=SC2034
85 | APP_BASE_NAME=${0##*/}
86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
87 |
88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
90 |
91 | # Use the maximum available, or set MAX_FD != -1 to use that value.
92 | MAX_FD=maximum
93 |
94 | warn () {
95 | echo "$*"
96 | } >&2
97 |
98 | die () {
99 | echo
100 | echo "$*"
101 | echo
102 | exit 1
103 | } >&2
104 |
105 | # OS specific support (must be 'true' or 'false').
106 | cygwin=false
107 | msys=false
108 | darwin=false
109 | nonstop=false
110 | case "$( uname )" in #(
111 | CYGWIN* ) cygwin=true ;; #(
112 | Darwin* ) darwin=true ;; #(
113 | MSYS* | MINGW* ) msys=true ;; #(
114 | NONSTOP* ) nonstop=true ;;
115 | esac
116 |
117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
118 |
119 |
120 | # Determine the Java command to use to start the JVM.
121 | if [ -n "$JAVA_HOME" ] ; then
122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
123 | # IBM's JDK on AIX uses strange locations for the executables
124 | JAVACMD=$JAVA_HOME/jre/sh/java
125 | else
126 | JAVACMD=$JAVA_HOME/bin/java
127 | fi
128 | if [ ! -x "$JAVACMD" ] ; then
129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
130 |
131 | Please set the JAVA_HOME variable in your environment to match the
132 | location of your Java installation."
133 | fi
134 | else
135 | JAVACMD=java
136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
137 |
138 | Please set the JAVA_HOME variable in your environment to match the
139 | location of your Java installation."
140 | fi
141 |
142 | # Increase the maximum file descriptors if we can.
143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
144 | case $MAX_FD in #(
145 | max*)
146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
147 | # shellcheck disable=SC3045
148 | MAX_FD=$( ulimit -H -n ) ||
149 | warn "Could not query maximum file descriptor limit"
150 | esac
151 | case $MAX_FD in #(
152 | '' | soft) :;; #(
153 | *)
154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
155 | # shellcheck disable=SC3045
156 | ulimit -n "$MAX_FD" ||
157 | warn "Could not set maximum file descriptor limit to $MAX_FD"
158 | esac
159 | fi
160 |
161 | # Collect all arguments for the java command, stacking in reverse order:
162 | # * args from the command line
163 | # * the main class name
164 | # * -classpath
165 | # * -D...appname settings
166 | # * --module-path (only if needed)
167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
168 |
169 | # For Cygwin or MSYS, switch paths to Windows format before running java
170 | if "$cygwin" || "$msys" ; then
171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
173 |
174 | JAVACMD=$( cygpath --unix "$JAVACMD" )
175 |
176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
177 | for arg do
178 | if
179 | case $arg in #(
180 | -*) false ;; # don't mess with options #(
181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
182 | [ -e "$t" ] ;; #(
183 | *) false ;;
184 | esac
185 | then
186 | arg=$( cygpath --path --ignore --mixed "$arg" )
187 | fi
188 | # Roll the args list around exactly as many times as the number of
189 | # args, so each arg winds up back in the position where it started, but
190 | # possibly modified.
191 | #
192 | # NB: a `for` loop captures its iteration list before it begins, so
193 | # changing the positional parameters here affects neither the number of
194 | # iterations, nor the values presented in `arg`.
195 | shift # remove old arg
196 | set -- "$@" "$arg" # push replacement arg
197 | done
198 | fi
199 |
200 | # Collect all arguments for the java command;
201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
202 | # shell script including quotes and variable substitutions, so put them in
203 | # double quotes to make sure that they get re-expanded; and
204 | # * put everything else in single quotes, so that it's not re-expanded.
205 |
206 | set -- \
207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
208 | -classpath "$CLASSPATH" \
209 | org.gradle.wrapper.GradleWrapperMain \
210 | "$@"
211 |
212 | # Stop when "xargs" is not available.
213 | if ! command -v xargs >/dev/null 2>&1
214 | then
215 | die "xargs is not available"
216 | fi
217 |
218 | # Use "xargs" to parse quoted args.
219 | #
220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
221 | #
222 | # In Bash we could simply go:
223 | #
224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
225 | # set -- "${ARGS[@]}" "$@"
226 | #
227 | # but POSIX shell has neither arrays nor command substitution, so instead we
228 | # post-process each arg (as a line of input to sed) to backslash-escape any
229 | # character that might be a shell metacharacter, then use eval to reverse
230 | # that process (while maintaining the separation between arguments), and wrap
231 | # the whole thing up as a single "set" statement.
232 | #
233 | # This will of course break if any of these variables contains a newline or
234 | # an unmatched quote.
235 | #
236 |
237 | eval "set -- $(
238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
239 | xargs -n1 |
240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
241 | tr '\n' ' '
242 | )" '"$@"'
243 |
244 | exec "$JAVACMD" "$@"
245 |
--------------------------------------------------------------------------------
/Example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - boost (1.76.0)
3 | - DoubleConversion (1.1.6)
4 | - FBLazyVector (0.72.1)
5 | - FBReactNativeSpec (0.72.1):
6 | - RCT-Folly (= 2021.07.22.00)
7 | - RCTRequired (= 0.72.1)
8 | - RCTTypeSafety (= 0.72.1)
9 | - React-Core (= 0.72.1)
10 | - React-jsi (= 0.72.1)
11 | - ReactCommon/turbomodule/core (= 0.72.1)
12 | - fmt (6.2.1)
13 | - glog (0.3.5)
14 | - RCT-Folly (2021.07.22.00):
15 | - boost
16 | - DoubleConversion
17 | - fmt (~> 6.2.1)
18 | - glog
19 | - RCT-Folly/Default (= 2021.07.22.00)
20 | - RCT-Folly/Default (2021.07.22.00):
21 | - boost
22 | - DoubleConversion
23 | - fmt (~> 6.2.1)
24 | - glog
25 | - RCTRequired (0.72.1)
26 | - RCTTypeSafety (0.72.1):
27 | - FBLazyVector (= 0.72.1)
28 | - RCTRequired (= 0.72.1)
29 | - React-Core (= 0.72.1)
30 | - React (0.72.1):
31 | - React-Core (= 0.72.1)
32 | - React-Core/DevSupport (= 0.72.1)
33 | - React-Core/RCTWebSocket (= 0.72.1)
34 | - React-RCTActionSheet (= 0.72.1)
35 | - React-RCTAnimation (= 0.72.1)
36 | - React-RCTBlob (= 0.72.1)
37 | - React-RCTImage (= 0.72.1)
38 | - React-RCTLinking (= 0.72.1)
39 | - React-RCTNetwork (= 0.72.1)
40 | - React-RCTSettings (= 0.72.1)
41 | - React-RCTText (= 0.72.1)
42 | - React-RCTVibration (= 0.72.1)
43 | - React-callinvoker (0.72.1)
44 | - React-Codegen (0.72.1):
45 | - DoubleConversion
46 | - FBReactNativeSpec
47 | - glog
48 | - RCT-Folly
49 | - RCTRequired
50 | - RCTTypeSafety
51 | - React-Core
52 | - React-jsc
53 | - React-jsi
54 | - React-jsiexecutor
55 | - React-NativeModulesApple
56 | - React-rncore
57 | - ReactCommon/turbomodule/bridging
58 | - ReactCommon/turbomodule/core
59 | - React-Core (0.72.1):
60 | - glog
61 | - RCT-Folly (= 2021.07.22.00)
62 | - React-Core/Default (= 0.72.1)
63 | - React-cxxreact
64 | - React-jsc
65 | - React-jsi
66 | - React-jsiexecutor
67 | - React-perflogger
68 | - React-runtimeexecutor
69 | - React-utils
70 | - SocketRocket (= 0.6.1)
71 | - Yoga
72 | - React-Core/CoreModulesHeaders (0.72.1):
73 | - glog
74 | - RCT-Folly (= 2021.07.22.00)
75 | - React-Core/Default
76 | - React-cxxreact
77 | - React-jsc
78 | - React-jsi
79 | - React-jsiexecutor
80 | - React-perflogger
81 | - React-runtimeexecutor
82 | - React-utils
83 | - SocketRocket (= 0.6.1)
84 | - Yoga
85 | - React-Core/Default (0.72.1):
86 | - glog
87 | - RCT-Folly (= 2021.07.22.00)
88 | - React-cxxreact
89 | - React-jsc
90 | - React-jsi
91 | - React-jsiexecutor
92 | - React-perflogger
93 | - React-runtimeexecutor
94 | - React-utils
95 | - SocketRocket (= 0.6.1)
96 | - Yoga
97 | - React-Core/DevSupport (0.72.1):
98 | - glog
99 | - RCT-Folly (= 2021.07.22.00)
100 | - React-Core/Default (= 0.72.1)
101 | - React-Core/RCTWebSocket (= 0.72.1)
102 | - React-cxxreact
103 | - React-jsc
104 | - React-jsi
105 | - React-jsiexecutor
106 | - React-jsinspector (= 0.72.1)
107 | - React-perflogger
108 | - React-runtimeexecutor
109 | - React-utils
110 | - SocketRocket (= 0.6.1)
111 | - Yoga
112 | - React-Core/RCTActionSheetHeaders (0.72.1):
113 | - glog
114 | - RCT-Folly (= 2021.07.22.00)
115 | - React-Core/Default
116 | - React-cxxreact
117 | - React-jsc
118 | - React-jsi
119 | - React-jsiexecutor
120 | - React-perflogger
121 | - React-runtimeexecutor
122 | - React-utils
123 | - SocketRocket (= 0.6.1)
124 | - Yoga
125 | - React-Core/RCTAnimationHeaders (0.72.1):
126 | - glog
127 | - RCT-Folly (= 2021.07.22.00)
128 | - React-Core/Default
129 | - React-cxxreact
130 | - React-jsc
131 | - React-jsi
132 | - React-jsiexecutor
133 | - React-perflogger
134 | - React-runtimeexecutor
135 | - React-utils
136 | - SocketRocket (= 0.6.1)
137 | - Yoga
138 | - React-Core/RCTBlobHeaders (0.72.1):
139 | - glog
140 | - RCT-Folly (= 2021.07.22.00)
141 | - React-Core/Default
142 | - React-cxxreact
143 | - React-jsc
144 | - React-jsi
145 | - React-jsiexecutor
146 | - React-perflogger
147 | - React-runtimeexecutor
148 | - React-utils
149 | - SocketRocket (= 0.6.1)
150 | - Yoga
151 | - React-Core/RCTImageHeaders (0.72.1):
152 | - glog
153 | - RCT-Folly (= 2021.07.22.00)
154 | - React-Core/Default
155 | - React-cxxreact
156 | - React-jsc
157 | - React-jsi
158 | - React-jsiexecutor
159 | - React-perflogger
160 | - React-runtimeexecutor
161 | - React-utils
162 | - SocketRocket (= 0.6.1)
163 | - Yoga
164 | - React-Core/RCTLinkingHeaders (0.72.1):
165 | - glog
166 | - RCT-Folly (= 2021.07.22.00)
167 | - React-Core/Default
168 | - React-cxxreact
169 | - React-jsc
170 | - React-jsi
171 | - React-jsiexecutor
172 | - React-perflogger
173 | - React-runtimeexecutor
174 | - React-utils
175 | - SocketRocket (= 0.6.1)
176 | - Yoga
177 | - React-Core/RCTNetworkHeaders (0.72.1):
178 | - glog
179 | - RCT-Folly (= 2021.07.22.00)
180 | - React-Core/Default
181 | - React-cxxreact
182 | - React-jsc
183 | - React-jsi
184 | - React-jsiexecutor
185 | - React-perflogger
186 | - React-runtimeexecutor
187 | - React-utils
188 | - SocketRocket (= 0.6.1)
189 | - Yoga
190 | - React-Core/RCTSettingsHeaders (0.72.1):
191 | - glog
192 | - RCT-Folly (= 2021.07.22.00)
193 | - React-Core/Default
194 | - React-cxxreact
195 | - React-jsc
196 | - React-jsi
197 | - React-jsiexecutor
198 | - React-perflogger
199 | - React-runtimeexecutor
200 | - React-utils
201 | - SocketRocket (= 0.6.1)
202 | - Yoga
203 | - React-Core/RCTTextHeaders (0.72.1):
204 | - glog
205 | - RCT-Folly (= 2021.07.22.00)
206 | - React-Core/Default
207 | - React-cxxreact
208 | - React-jsc
209 | - React-jsi
210 | - React-jsiexecutor
211 | - React-perflogger
212 | - React-runtimeexecutor
213 | - React-utils
214 | - SocketRocket (= 0.6.1)
215 | - Yoga
216 | - React-Core/RCTVibrationHeaders (0.72.1):
217 | - glog
218 | - RCT-Folly (= 2021.07.22.00)
219 | - React-Core/Default
220 | - React-cxxreact
221 | - React-jsc
222 | - React-jsi
223 | - React-jsiexecutor
224 | - React-perflogger
225 | - React-runtimeexecutor
226 | - React-utils
227 | - SocketRocket (= 0.6.1)
228 | - Yoga
229 | - React-Core/RCTWebSocket (0.72.1):
230 | - glog
231 | - RCT-Folly (= 2021.07.22.00)
232 | - React-Core/Default (= 0.72.1)
233 | - React-cxxreact
234 | - React-jsc
235 | - React-jsi
236 | - React-jsiexecutor
237 | - React-perflogger
238 | - React-runtimeexecutor
239 | - React-utils
240 | - SocketRocket (= 0.6.1)
241 | - Yoga
242 | - React-CoreModules (0.72.1):
243 | - RCT-Folly (= 2021.07.22.00)
244 | - RCTTypeSafety (= 0.72.1)
245 | - React-Codegen (= 0.72.1)
246 | - React-Core/CoreModulesHeaders (= 0.72.1)
247 | - React-jsi (= 0.72.1)
248 | - React-RCTBlob
249 | - React-RCTImage (= 0.72.1)
250 | - ReactCommon/turbomodule/core (= 0.72.1)
251 | - SocketRocket (= 0.6.1)
252 | - React-cxxreact (0.72.1):
253 | - boost (= 1.76.0)
254 | - DoubleConversion
255 | - glog
256 | - RCT-Folly (= 2021.07.22.00)
257 | - React-callinvoker (= 0.72.1)
258 | - React-jsi (= 0.72.1)
259 | - React-jsinspector (= 0.72.1)
260 | - React-logger (= 0.72.1)
261 | - React-perflogger (= 0.72.1)
262 | - React-runtimeexecutor (= 0.72.1)
263 | - React-debug (0.72.1)
264 | - React-jsc (0.72.1):
265 | - React-jsc/Fabric (= 0.72.1)
266 | - React-jsi (= 0.72.1)
267 | - React-jsc/Fabric (0.72.1):
268 | - React-jsi (= 0.72.1)
269 | - React-jsi (0.72.1):
270 | - boost (= 1.76.0)
271 | - DoubleConversion
272 | - glog
273 | - RCT-Folly (= 2021.07.22.00)
274 | - React-jsiexecutor (0.72.1):
275 | - DoubleConversion
276 | - glog
277 | - RCT-Folly (= 2021.07.22.00)
278 | - React-cxxreact (= 0.72.1)
279 | - React-jsi (= 0.72.1)
280 | - React-perflogger (= 0.72.1)
281 | - React-jsinspector (0.72.1)
282 | - React-logger (0.72.1):
283 | - glog
284 | - react-native-get-random-values (1.9.0):
285 | - React-Core
286 | - React-NativeModulesApple (0.72.1):
287 | - React-callinvoker
288 | - React-Core
289 | - React-cxxreact
290 | - React-jsi
291 | - React-runtimeexecutor
292 | - ReactCommon/turbomodule/bridging
293 | - ReactCommon/turbomodule/core
294 | - React-perflogger (0.72.1)
295 | - React-RCTActionSheet (0.72.1):
296 | - React-Core/RCTActionSheetHeaders (= 0.72.1)
297 | - React-RCTAnimation (0.72.1):
298 | - RCT-Folly (= 2021.07.22.00)
299 | - RCTTypeSafety (= 0.72.1)
300 | - React-Codegen (= 0.72.1)
301 | - React-Core/RCTAnimationHeaders (= 0.72.1)
302 | - React-jsi (= 0.72.1)
303 | - ReactCommon/turbomodule/core (= 0.72.1)
304 | - React-RCTAppDelegate (0.72.1):
305 | - RCT-Folly
306 | - RCTRequired
307 | - RCTTypeSafety
308 | - React-Core
309 | - React-CoreModules
310 | - React-jsc
311 | - React-NativeModulesApple
312 | - React-RCTImage
313 | - React-RCTNetwork
314 | - React-runtimescheduler
315 | - ReactCommon/turbomodule/core
316 | - React-RCTBlob (0.72.1):
317 | - RCT-Folly (= 2021.07.22.00)
318 | - React-Codegen (= 0.72.1)
319 | - React-Core/RCTBlobHeaders (= 0.72.1)
320 | - React-Core/RCTWebSocket (= 0.72.1)
321 | - React-jsi (= 0.72.1)
322 | - React-RCTNetwork (= 0.72.1)
323 | - ReactCommon/turbomodule/core (= 0.72.1)
324 | - React-RCTImage (0.72.1):
325 | - RCT-Folly (= 2021.07.22.00)
326 | - RCTTypeSafety (= 0.72.1)
327 | - React-Codegen (= 0.72.1)
328 | - React-Core/RCTImageHeaders (= 0.72.1)
329 | - React-jsi (= 0.72.1)
330 | - React-RCTNetwork (= 0.72.1)
331 | - ReactCommon/turbomodule/core (= 0.72.1)
332 | - React-RCTLinking (0.72.1):
333 | - React-Codegen (= 0.72.1)
334 | - React-Core/RCTLinkingHeaders (= 0.72.1)
335 | - React-jsi (= 0.72.1)
336 | - ReactCommon/turbomodule/core (= 0.72.1)
337 | - React-RCTNetwork (0.72.1):
338 | - RCT-Folly (= 2021.07.22.00)
339 | - RCTTypeSafety (= 0.72.1)
340 | - React-Codegen (= 0.72.1)
341 | - React-Core/RCTNetworkHeaders (= 0.72.1)
342 | - React-jsi (= 0.72.1)
343 | - ReactCommon/turbomodule/core (= 0.72.1)
344 | - React-RCTSettings (0.72.1):
345 | - RCT-Folly (= 2021.07.22.00)
346 | - RCTTypeSafety (= 0.72.1)
347 | - React-Codegen (= 0.72.1)
348 | - React-Core/RCTSettingsHeaders (= 0.72.1)
349 | - React-jsi (= 0.72.1)
350 | - ReactCommon/turbomodule/core (= 0.72.1)
351 | - React-RCTText (0.72.1):
352 | - React-Core/RCTTextHeaders (= 0.72.1)
353 | - React-RCTVibration (0.72.1):
354 | - RCT-Folly (= 2021.07.22.00)
355 | - React-Codegen (= 0.72.1)
356 | - React-Core/RCTVibrationHeaders (= 0.72.1)
357 | - React-jsi (= 0.72.1)
358 | - ReactCommon/turbomodule/core (= 0.72.1)
359 | - React-rncore (0.72.1)
360 | - React-runtimeexecutor (0.72.1):
361 | - React-jsi (= 0.72.1)
362 | - React-runtimescheduler (0.72.1):
363 | - glog
364 | - RCT-Folly (= 2021.07.22.00)
365 | - React-callinvoker
366 | - React-debug
367 | - React-jsi
368 | - React-runtimeexecutor
369 | - React-utils (0.72.1):
370 | - glog
371 | - RCT-Folly (= 2021.07.22.00)
372 | - React-debug
373 | - ReactCommon/turbomodule/bridging (0.72.1):
374 | - DoubleConversion
375 | - glog
376 | - RCT-Folly (= 2021.07.22.00)
377 | - React-callinvoker (= 0.72.1)
378 | - React-cxxreact (= 0.72.1)
379 | - React-jsi (= 0.72.1)
380 | - React-logger (= 0.72.1)
381 | - React-perflogger (= 0.72.1)
382 | - ReactCommon/turbomodule/core (0.72.1):
383 | - DoubleConversion
384 | - glog
385 | - RCT-Folly (= 2021.07.22.00)
386 | - React-callinvoker (= 0.72.1)
387 | - React-cxxreact (= 0.72.1)
388 | - React-jsi (= 0.72.1)
389 | - React-logger (= 0.72.1)
390 | - React-perflogger (= 0.72.1)
391 | - RNReanimated (3.3.0):
392 | - DoubleConversion
393 | - FBLazyVector
394 | - glog
395 | - RCT-Folly
396 | - RCTRequired
397 | - RCTTypeSafety
398 | - React-callinvoker
399 | - React-Core
400 | - React-Core/DevSupport
401 | - React-Core/RCTWebSocket
402 | - React-CoreModules
403 | - React-cxxreact
404 | - React-jsi
405 | - React-jsiexecutor
406 | - React-jsinspector
407 | - React-RCTActionSheet
408 | - React-RCTAnimation
409 | - React-RCTAppDelegate
410 | - React-RCTBlob
411 | - React-RCTImage
412 | - React-RCTLinking
413 | - React-RCTNetwork
414 | - React-RCTSettings
415 | - React-RCTText
416 | - ReactCommon/turbomodule/core
417 | - Yoga
418 | - SocketRocket (0.6.1)
419 | - Yoga (1.14.0)
420 |
421 | DEPENDENCIES:
422 | - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
423 | - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
424 | - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
425 | - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
426 | - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
427 | - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
428 | - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
429 | - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
430 | - React (from `../node_modules/react-native/`)
431 | - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
432 | - React-Codegen (from `build/generated/ios`)
433 | - React-Core (from `../node_modules/react-native/`)
434 | - React-Core/RCTWebSocket (from `../node_modules/react-native/`)
435 | - React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
436 | - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
437 | - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`)
438 | - React-jsc (from `../node_modules/react-native/ReactCommon/jsc`)
439 | - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
440 | - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
441 | - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
442 | - React-logger (from `../node_modules/react-native/ReactCommon/logger`)
443 | - react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
444 | - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
445 | - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
446 | - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
447 | - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
448 | - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`)
449 | - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
450 | - React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
451 | - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
452 | - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
453 | - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
454 | - React-RCTText (from `../node_modules/react-native/Libraries/Text`)
455 | - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
456 | - React-rncore (from `../node_modules/react-native/ReactCommon`)
457 | - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
458 | - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
459 | - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
460 | - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
461 | - RNReanimated (from `../node_modules/react-native-reanimated`)
462 | - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
463 |
464 | SPEC REPOS:
465 | trunk:
466 | - fmt
467 | - SocketRocket
468 |
469 | EXTERNAL SOURCES:
470 | boost:
471 | :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
472 | DoubleConversion:
473 | :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
474 | FBLazyVector:
475 | :path: "../node_modules/react-native/Libraries/FBLazyVector"
476 | FBReactNativeSpec:
477 | :path: "../node_modules/react-native/React/FBReactNativeSpec"
478 | glog:
479 | :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
480 | RCT-Folly:
481 | :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
482 | RCTRequired:
483 | :path: "../node_modules/react-native/Libraries/RCTRequired"
484 | RCTTypeSafety:
485 | :path: "../node_modules/react-native/Libraries/TypeSafety"
486 | React:
487 | :path: "../node_modules/react-native/"
488 | React-callinvoker:
489 | :path: "../node_modules/react-native/ReactCommon/callinvoker"
490 | React-Codegen:
491 | :path: build/generated/ios
492 | React-Core:
493 | :path: "../node_modules/react-native/"
494 | React-CoreModules:
495 | :path: "../node_modules/react-native/React/CoreModules"
496 | React-cxxreact:
497 | :path: "../node_modules/react-native/ReactCommon/cxxreact"
498 | React-debug:
499 | :path: "../node_modules/react-native/ReactCommon/react/debug"
500 | React-jsc:
501 | :path: "../node_modules/react-native/ReactCommon/jsc"
502 | React-jsi:
503 | :path: "../node_modules/react-native/ReactCommon/jsi"
504 | React-jsiexecutor:
505 | :path: "../node_modules/react-native/ReactCommon/jsiexecutor"
506 | React-jsinspector:
507 | :path: "../node_modules/react-native/ReactCommon/jsinspector"
508 | React-logger:
509 | :path: "../node_modules/react-native/ReactCommon/logger"
510 | react-native-get-random-values:
511 | :path: "../node_modules/react-native-get-random-values"
512 | React-NativeModulesApple:
513 | :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
514 | React-perflogger:
515 | :path: "../node_modules/react-native/ReactCommon/reactperflogger"
516 | React-RCTActionSheet:
517 | :path: "../node_modules/react-native/Libraries/ActionSheetIOS"
518 | React-RCTAnimation:
519 | :path: "../node_modules/react-native/Libraries/NativeAnimation"
520 | React-RCTAppDelegate:
521 | :path: "../node_modules/react-native/Libraries/AppDelegate"
522 | React-RCTBlob:
523 | :path: "../node_modules/react-native/Libraries/Blob"
524 | React-RCTImage:
525 | :path: "../node_modules/react-native/Libraries/Image"
526 | React-RCTLinking:
527 | :path: "../node_modules/react-native/Libraries/LinkingIOS"
528 | React-RCTNetwork:
529 | :path: "../node_modules/react-native/Libraries/Network"
530 | React-RCTSettings:
531 | :path: "../node_modules/react-native/Libraries/Settings"
532 | React-RCTText:
533 | :path: "../node_modules/react-native/Libraries/Text"
534 | React-RCTVibration:
535 | :path: "../node_modules/react-native/Libraries/Vibration"
536 | React-rncore:
537 | :path: "../node_modules/react-native/ReactCommon"
538 | React-runtimeexecutor:
539 | :path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
540 | React-runtimescheduler:
541 | :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler"
542 | React-utils:
543 | :path: "../node_modules/react-native/ReactCommon/react/utils"
544 | ReactCommon:
545 | :path: "../node_modules/react-native/ReactCommon"
546 | RNReanimated:
547 | :path: "../node_modules/react-native-reanimated"
548 | Yoga:
549 | :path: "../node_modules/react-native/ReactCommon/yoga"
550 |
551 | SPEC CHECKSUMS:
552 | boost: 57d2868c099736d80fcd648bf211b4431e51a558
553 | DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
554 | FBLazyVector: 55cd4593d570bd9e5e227488d637ce6a9581ce51
555 | FBReactNativeSpec: 799b0e1a1561699cd0e424e24fe5624da38402f0
556 | fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
557 | glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
558 | RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1
559 | RCTRequired: c52ee8fb2b35c1b54031dd8e92d88ad4dba8f2ce
560 | RCTTypeSafety: 75fa444becadf0ebfa0a456b8c64560c7c89c7df
561 | React: 3e5b3962f27b7334eaf5517a35b3434503df35ad
562 | React-callinvoker: c3a225610efe0caadac78da53b6fe78e53eb2b03
563 | React-Codegen: 5284c73a9915a7ce641a679423eb52cc799a2c0c
564 | React-Core: ea8efd7340e01f11d033782a90786f9e1532e598
565 | React-CoreModules: ab635016811b610a93e873485f6f900ce0582192
566 | React-cxxreact: 367c31ce845fc91f1d9ff60726c012e36ebde657
567 | React-debug: 8aa2bd54b0f0011049300ce3339b0e51254ef3b5
568 | React-jsc: 9a0d9ce5353c5542ddc1e10c4988e8b2f2fd4d0a
569 | React-jsi: 085949ea16818b34c929649b941d3adbadb2cd63
570 | React-jsiexecutor: d870d2b6fe0a060e2dcf675e9d801552ead06c84
571 | React-jsinspector: d0b5bfd1085599265f4212034321e829bdf83cc0
572 | React-logger: b8103c9b04e707b50cdd2b1aeb382483900cbb37
573 | react-native-get-random-values: dee677497c6a740b71e5612e8dbd83e7539ed5bb
574 | React-NativeModulesApple: a95134487a26bbfd83326f8d7af335739cb17421
575 | React-perflogger: 3d501f34c8d4b10cb75f348e43591765788525ad
576 | React-RCTActionSheet: f5335572c979198c0c3daff67b07bd1ad8370c1d
577 | React-RCTAnimation: 5d0d31a4f9c49a70f93f32e4da098fb49b5ae0b3
578 | React-RCTAppDelegate: 3fe7e89add0f83db65c86b5df0471f1d759bf9fa
579 | React-RCTBlob: 0bd301dfd41045f833945996cfa6fafa112445a8
580 | React-RCTImage: e15d22db53406401cdd1407ce51080a66a9c7ed4
581 | React-RCTLinking: 39815800ec79d6fb15e6329244d195ebeabf7541
582 | React-RCTNetwork: 2a6548e13d2577b112d4250ac5be74ae62e1e86b
583 | React-RCTSettings: a76aee44d5398144646be146c334b15c90ad9582
584 | React-RCTText: afad390f3838f210c2bc9e1a19bb048003b2a771
585 | React-RCTVibration: 29bbaa5c57c02dc036d7e557584b492000b1d3e7
586 | React-rncore: 50966ce412d63bee9ffe5c98249857c23870a3c4
587 | React-runtimeexecutor: d129f2b53d61298093d7c7d8ebfafa664f911ce6
588 | React-runtimescheduler: 84546e214feb91c1b51081e59b87d7df4973f2d8
589 | React-utils: 0a70ea97d4e2749f336b450c082905be1d389435
590 | ReactCommon: 4cbf891957cb9fdb7193f85f8dded6c62e6d112e
591 | RNReanimated: 3ffa3d63576ecd26a4f8772d03029cccaf41b5d7
592 | SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
593 | Yoga: 65286bb6a07edce5e4fe8c90774da977ae8fc009
594 |
595 | PODFILE CHECKSUM: ccd36ec4a4bee079079df91b2a3df397a1effb8e
596 |
597 | COCOAPODS: 1.12.0
598 |
--------------------------------------------------------------------------------
/Example/ios/Example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 54;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 00E356F31AD99517003FC87E /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* ExampleTests.m */; };
11 | 0C80B921A6F3F58F76C31292 /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-Example.a */; };
12 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
13 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
14 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
15 | 7699B88040F8A987B510C191 /* libPods-Example-ExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Example-ExampleTests.a */; };
16 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXContainerItemProxy section */
20 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
21 | isa = PBXContainerItemProxy;
22 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
23 | proxyType = 1;
24 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
25 | remoteInfo = Example;
26 | };
27 | /* End PBXContainerItemProxy section */
28 |
29 | /* Begin PBXFileReference section */
30 | 00E356EE1AD99517003FC87E /* ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
31 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
32 | 00E356F21AD99517003FC87E /* ExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleTests.m; sourceTree = ""; };
33 | 13B07F961A680F5B00A75B9A /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
34 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Example/AppDelegate.h; sourceTree = ""; };
35 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Example/AppDelegate.mm; sourceTree = ""; };
36 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Example/Images.xcassets; sourceTree = ""; };
37 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = ""; };
38 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = ""; };
39 | 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Example-ExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example-ExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
40 | 3B4392A12AC88292D35C810B /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; };
41 | 5709B34CF0A7D63546082F79 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; };
42 | 5B7EB9410499542E8C5724F5 /* Pods-Example-ExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-ExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests.debug.xcconfig"; sourceTree = ""; };
43 | 5DCACB8F33CDC322A6C60F78 /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Example/LaunchScreen.storyboard; sourceTree = ""; };
45 | 89C6BE57DB24E9ADA2F236DE /* Pods-Example-ExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example-ExampleTests.release.xcconfig"; path = "Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests.release.xcconfig"; sourceTree = ""; };
46 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
47 | /* End PBXFileReference section */
48 |
49 | /* Begin PBXFrameworksBuildPhase section */
50 | 00E356EB1AD99517003FC87E /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | 7699B88040F8A987B510C191 /* libPods-Example-ExampleTests.a in Frameworks */,
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
59 | isa = PBXFrameworksBuildPhase;
60 | buildActionMask = 2147483647;
61 | files = (
62 | 0C80B921A6F3F58F76C31292 /* libPods-Example.a in Frameworks */,
63 | );
64 | runOnlyForDeploymentPostprocessing = 0;
65 | };
66 | /* End PBXFrameworksBuildPhase section */
67 |
68 | /* Begin PBXGroup section */
69 | 00E356EF1AD99517003FC87E /* ExampleTests */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 00E356F21AD99517003FC87E /* ExampleTests.m */,
73 | 00E356F01AD99517003FC87E /* Supporting Files */,
74 | );
75 | path = ExampleTests;
76 | sourceTree = "";
77 | };
78 | 00E356F01AD99517003FC87E /* Supporting Files */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 00E356F11AD99517003FC87E /* Info.plist */,
82 | );
83 | name = "Supporting Files";
84 | sourceTree = "";
85 | };
86 | 13B07FAE1A68108700A75B9A /* Example */ = {
87 | isa = PBXGroup;
88 | children = (
89 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
90 | 13B07FB01A68108700A75B9A /* AppDelegate.mm */,
91 | 13B07FB51A68108700A75B9A /* Images.xcassets */,
92 | 13B07FB61A68108700A75B9A /* Info.plist */,
93 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
94 | 13B07FB71A68108700A75B9A /* main.m */,
95 | );
96 | name = Example;
97 | sourceTree = "";
98 | };
99 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
100 | isa = PBXGroup;
101 | children = (
102 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
103 | 5DCACB8F33CDC322A6C60F78 /* libPods-Example.a */,
104 | 19F6CBCC0A4E27FBF8BF4A61 /* libPods-Example-ExampleTests.a */,
105 | );
106 | name = Frameworks;
107 | sourceTree = "";
108 | };
109 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
110 | isa = PBXGroup;
111 | children = (
112 | );
113 | name = Libraries;
114 | sourceTree = "";
115 | };
116 | 83CBB9F61A601CBA00E9B192 = {
117 | isa = PBXGroup;
118 | children = (
119 | 13B07FAE1A68108700A75B9A /* Example */,
120 | 832341AE1AAA6A7D00B99B32 /* Libraries */,
121 | 00E356EF1AD99517003FC87E /* ExampleTests */,
122 | 83CBBA001A601CBA00E9B192 /* Products */,
123 | 2D16E6871FA4F8E400B85C8A /* Frameworks */,
124 | BBD78D7AC51CEA395F1C20DB /* Pods */,
125 | );
126 | indentWidth = 2;
127 | sourceTree = "";
128 | tabWidth = 2;
129 | usesTabs = 0;
130 | };
131 | 83CBBA001A601CBA00E9B192 /* Products */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 13B07F961A680F5B00A75B9A /* Example.app */,
135 | 00E356EE1AD99517003FC87E /* ExampleTests.xctest */,
136 | );
137 | name = Products;
138 | sourceTree = "";
139 | };
140 | BBD78D7AC51CEA395F1C20DB /* Pods */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 3B4392A12AC88292D35C810B /* Pods-Example.debug.xcconfig */,
144 | 5709B34CF0A7D63546082F79 /* Pods-Example.release.xcconfig */,
145 | 5B7EB9410499542E8C5724F5 /* Pods-Example-ExampleTests.debug.xcconfig */,
146 | 89C6BE57DB24E9ADA2F236DE /* Pods-Example-ExampleTests.release.xcconfig */,
147 | );
148 | path = Pods;
149 | sourceTree = "";
150 | };
151 | /* End PBXGroup section */
152 |
153 | /* Begin PBXNativeTarget section */
154 | 00E356ED1AD99517003FC87E /* ExampleTests */ = {
155 | isa = PBXNativeTarget;
156 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ExampleTests" */;
157 | buildPhases = (
158 | A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
159 | 00E356EA1AD99517003FC87E /* Sources */,
160 | 00E356EB1AD99517003FC87E /* Frameworks */,
161 | 00E356EC1AD99517003FC87E /* Resources */,
162 | F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
163 | );
164 | buildRules = (
165 | );
166 | dependencies = (
167 | 00E356F51AD99517003FC87E /* PBXTargetDependency */,
168 | );
169 | name = ExampleTests;
170 | productName = ExampleTests;
171 | productReference = 00E356EE1AD99517003FC87E /* ExampleTests.xctest */;
172 | productType = "com.apple.product-type.bundle.unit-test";
173 | };
174 | 13B07F861A680F5B00A75B9A /* Example */ = {
175 | isa = PBXNativeTarget;
176 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Example" */;
177 | buildPhases = (
178 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
179 | FD10A7F022414F080027D42C /* Start Packager */,
180 | 13B07F871A680F5B00A75B9A /* Sources */,
181 | 13B07F8C1A680F5B00A75B9A /* Frameworks */,
182 | 13B07F8E1A680F5B00A75B9A /* Resources */,
183 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
184 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
185 | );
186 | buildRules = (
187 | );
188 | dependencies = (
189 | );
190 | name = Example;
191 | productName = Example;
192 | productReference = 13B07F961A680F5B00A75B9A /* Example.app */;
193 | productType = "com.apple.product-type.application";
194 | };
195 | /* End PBXNativeTarget section */
196 |
197 | /* Begin PBXProject section */
198 | 83CBB9F71A601CBA00E9B192 /* Project object */ = {
199 | isa = PBXProject;
200 | attributes = {
201 | LastUpgradeCheck = 1210;
202 | TargetAttributes = {
203 | 00E356ED1AD99517003FC87E = {
204 | CreatedOnToolsVersion = 6.2;
205 | TestTargetID = 13B07F861A680F5B00A75B9A;
206 | };
207 | 13B07F861A680F5B00A75B9A = {
208 | LastSwiftMigration = 1120;
209 | };
210 | };
211 | };
212 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */;
213 | compatibilityVersion = "Xcode 12.0";
214 | developmentRegion = en;
215 | hasScannedForEncodings = 0;
216 | knownRegions = (
217 | en,
218 | Base,
219 | );
220 | mainGroup = 83CBB9F61A601CBA00E9B192;
221 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
222 | projectDirPath = "";
223 | projectRoot = "";
224 | targets = (
225 | 13B07F861A680F5B00A75B9A /* Example */,
226 | 00E356ED1AD99517003FC87E /* ExampleTests */,
227 | );
228 | };
229 | /* End PBXProject section */
230 |
231 | /* Begin PBXResourcesBuildPhase section */
232 | 00E356EC1AD99517003FC87E /* Resources */ = {
233 | isa = PBXResourcesBuildPhase;
234 | buildActionMask = 2147483647;
235 | files = (
236 | );
237 | runOnlyForDeploymentPostprocessing = 0;
238 | };
239 | 13B07F8E1A680F5B00A75B9A /* Resources */ = {
240 | isa = PBXResourcesBuildPhase;
241 | buildActionMask = 2147483647;
242 | files = (
243 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
244 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
245 | );
246 | runOnlyForDeploymentPostprocessing = 0;
247 | };
248 | /* End PBXResourcesBuildPhase section */
249 |
250 | /* Begin PBXShellScriptBuildPhase section */
251 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
252 | isa = PBXShellScriptBuildPhase;
253 | buildActionMask = 2147483647;
254 | files = (
255 | );
256 | inputPaths = (
257 | "$(SRCROOT)/.xcode.env.local",
258 | "$(SRCROOT)/.xcode.env",
259 | );
260 | name = "Bundle React Native code and images";
261 | outputPaths = (
262 | );
263 | runOnlyForDeploymentPostprocessing = 0;
264 | shellPath = /bin/sh;
265 | shellScript = "set -e\n\nexport BUNDLE_COMMAND=esbuild-bundle\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
266 | };
267 | A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
268 | isa = PBXShellScriptBuildPhase;
269 | buildActionMask = 2147483647;
270 | files = (
271 | );
272 | inputFileListPaths = (
273 | );
274 | inputPaths = (
275 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
276 | "${PODS_ROOT}/Manifest.lock",
277 | );
278 | name = "[CP] Check Pods Manifest.lock";
279 | outputFileListPaths = (
280 | );
281 | outputPaths = (
282 | "$(DERIVED_FILE_DIR)/Pods-Example-ExampleTests-checkManifestLockResult.txt",
283 | );
284 | runOnlyForDeploymentPostprocessing = 0;
285 | shellPath = /bin/sh;
286 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
287 | showEnvVarsInLog = 0;
288 | };
289 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
290 | isa = PBXShellScriptBuildPhase;
291 | buildActionMask = 2147483647;
292 | files = (
293 | );
294 | inputFileListPaths = (
295 | );
296 | inputPaths = (
297 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
298 | "${PODS_ROOT}/Manifest.lock",
299 | );
300 | name = "[CP] Check Pods Manifest.lock";
301 | outputFileListPaths = (
302 | );
303 | outputPaths = (
304 | "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt",
305 | );
306 | runOnlyForDeploymentPostprocessing = 0;
307 | shellPath = /bin/sh;
308 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
309 | showEnvVarsInLog = 0;
310 | };
311 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
312 | isa = PBXShellScriptBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | );
316 | inputFileListPaths = (
317 | "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-resources-${CONFIGURATION}-input-files.xcfilelist",
318 | );
319 | name = "[CP] Copy Pods Resources";
320 | outputFileListPaths = (
321 | "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-resources-${CONFIGURATION}-output-files.xcfilelist",
322 | );
323 | runOnlyForDeploymentPostprocessing = 0;
324 | shellPath = /bin/sh;
325 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n";
326 | showEnvVarsInLog = 0;
327 | };
328 | F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
329 | isa = PBXShellScriptBuildPhase;
330 | buildActionMask = 2147483647;
331 | files = (
332 | );
333 | inputFileListPaths = (
334 | "${PODS_ROOT}/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-resources-${CONFIGURATION}-input-files.xcfilelist",
335 | );
336 | name = "[CP] Copy Pods Resources";
337 | outputFileListPaths = (
338 | "${PODS_ROOT}/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-resources-${CONFIGURATION}-output-files.xcfilelist",
339 | );
340 | runOnlyForDeploymentPostprocessing = 0;
341 | shellPath = /bin/sh;
342 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example-ExampleTests/Pods-Example-ExampleTests-resources.sh\"\n";
343 | showEnvVarsInLog = 0;
344 | };
345 | FD10A7F022414F080027D42C /* Start Packager */ = {
346 | isa = PBXShellScriptBuildPhase;
347 | buildActionMask = 2147483647;
348 | files = (
349 | );
350 | inputFileListPaths = (
351 | );
352 | inputPaths = (
353 | );
354 | name = "Start Packager";
355 | outputFileListPaths = (
356 | );
357 | outputPaths = (
358 | );
359 | runOnlyForDeploymentPostprocessing = 0;
360 | shellPath = /bin/sh;
361 | shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
362 | showEnvVarsInLog = 0;
363 | };
364 | /* End PBXShellScriptBuildPhase section */
365 |
366 | /* Begin PBXSourcesBuildPhase section */
367 | 00E356EA1AD99517003FC87E /* Sources */ = {
368 | isa = PBXSourcesBuildPhase;
369 | buildActionMask = 2147483647;
370 | files = (
371 | 00E356F31AD99517003FC87E /* ExampleTests.m in Sources */,
372 | );
373 | runOnlyForDeploymentPostprocessing = 0;
374 | };
375 | 13B07F871A680F5B00A75B9A /* Sources */ = {
376 | isa = PBXSourcesBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
380 | 13B07FC11A68108700A75B9A /* main.m in Sources */,
381 | );
382 | runOnlyForDeploymentPostprocessing = 0;
383 | };
384 | /* End PBXSourcesBuildPhase section */
385 |
386 | /* Begin PBXTargetDependency section */
387 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
388 | isa = PBXTargetDependency;
389 | target = 13B07F861A680F5B00A75B9A /* Example */;
390 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
391 | };
392 | /* End PBXTargetDependency section */
393 |
394 | /* Begin XCBuildConfiguration section */
395 | 00E356F61AD99517003FC87E /* Debug */ = {
396 | isa = XCBuildConfiguration;
397 | baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-Example-ExampleTests.debug.xcconfig */;
398 | buildSettings = {
399 | BUNDLE_LOADER = "$(TEST_HOST)";
400 | GCC_PREPROCESSOR_DEFINITIONS = (
401 | "DEBUG=1",
402 | "$(inherited)",
403 | );
404 | INFOPLIST_FILE = ExampleTests/Info.plist;
405 | IPHONEOS_DEPLOYMENT_TARGET = 12.4;
406 | LD_RUNPATH_SEARCH_PATHS = (
407 | "$(inherited)",
408 | "@executable_path/Frameworks",
409 | "@loader_path/Frameworks",
410 | );
411 | OTHER_LDFLAGS = (
412 | "-ObjC",
413 | "-lc++",
414 | "$(inherited)",
415 | );
416 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
417 | PRODUCT_NAME = "$(TARGET_NAME)";
418 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
419 | };
420 | name = Debug;
421 | };
422 | 00E356F71AD99517003FC87E /* Release */ = {
423 | isa = XCBuildConfiguration;
424 | baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-Example-ExampleTests.release.xcconfig */;
425 | buildSettings = {
426 | BUNDLE_LOADER = "$(TEST_HOST)";
427 | COPY_PHASE_STRIP = NO;
428 | INFOPLIST_FILE = ExampleTests/Info.plist;
429 | IPHONEOS_DEPLOYMENT_TARGET = 12.4;
430 | LD_RUNPATH_SEARCH_PATHS = (
431 | "$(inherited)",
432 | "@executable_path/Frameworks",
433 | "@loader_path/Frameworks",
434 | );
435 | OTHER_LDFLAGS = (
436 | "-ObjC",
437 | "-lc++",
438 | "$(inherited)",
439 | );
440 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
441 | PRODUCT_NAME = "$(TARGET_NAME)";
442 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
443 | };
444 | name = Release;
445 | };
446 | 13B07F941A680F5B00A75B9A /* Debug */ = {
447 | isa = XCBuildConfiguration;
448 | baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-Example.debug.xcconfig */;
449 | buildSettings = {
450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
451 | CLANG_ENABLE_MODULES = YES;
452 | CURRENT_PROJECT_VERSION = 1;
453 | ENABLE_BITCODE = NO;
454 | INFOPLIST_FILE = Example/Info.plist;
455 | LD_RUNPATH_SEARCH_PATHS = (
456 | "$(inherited)",
457 | "@executable_path/Frameworks",
458 | );
459 | MARKETING_VERSION = 1.0;
460 | OTHER_LDFLAGS = (
461 | "$(inherited)",
462 | "-ObjC",
463 | "-lc++",
464 | );
465 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
466 | PRODUCT_NAME = Example;
467 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
468 | SWIFT_VERSION = 5.0;
469 | VERSIONING_SYSTEM = "apple-generic";
470 | };
471 | name = Debug;
472 | };
473 | 13B07F951A680F5B00A75B9A /* Release */ = {
474 | isa = XCBuildConfiguration;
475 | baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-Example.release.xcconfig */;
476 | buildSettings = {
477 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
478 | CLANG_ENABLE_MODULES = YES;
479 | CURRENT_PROJECT_VERSION = 1;
480 | INFOPLIST_FILE = Example/Info.plist;
481 | LD_RUNPATH_SEARCH_PATHS = (
482 | "$(inherited)",
483 | "@executable_path/Frameworks",
484 | );
485 | MARKETING_VERSION = 1.0;
486 | OTHER_LDFLAGS = (
487 | "$(inherited)",
488 | "-ObjC",
489 | "-lc++",
490 | );
491 | PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
492 | PRODUCT_NAME = Example;
493 | SWIFT_VERSION = 5.0;
494 | VERSIONING_SYSTEM = "apple-generic";
495 | };
496 | name = Release;
497 | };
498 | 83CBBA201A601CBA00E9B192 /* Debug */ = {
499 | isa = XCBuildConfiguration;
500 | buildSettings = {
501 | ALWAYS_SEARCH_USER_PATHS = NO;
502 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
503 | CLANG_CXX_LANGUAGE_STANDARD = "c++17";
504 | CLANG_CXX_LIBRARY = "libc++";
505 | CLANG_ENABLE_MODULES = YES;
506 | CLANG_ENABLE_OBJC_ARC = YES;
507 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
508 | CLANG_WARN_BOOL_CONVERSION = YES;
509 | CLANG_WARN_COMMA = YES;
510 | CLANG_WARN_CONSTANT_CONVERSION = YES;
511 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
512 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
513 | CLANG_WARN_EMPTY_BODY = YES;
514 | CLANG_WARN_ENUM_CONVERSION = YES;
515 | CLANG_WARN_INFINITE_RECURSION = YES;
516 | CLANG_WARN_INT_CONVERSION = YES;
517 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
518 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
519 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
520 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
521 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
522 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
523 | CLANG_WARN_STRICT_PROTOTYPES = YES;
524 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
525 | CLANG_WARN_UNREACHABLE_CODE = YES;
526 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
527 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
528 | COPY_PHASE_STRIP = NO;
529 | ENABLE_STRICT_OBJC_MSGSEND = YES;
530 | ENABLE_TESTABILITY = YES;
531 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
532 | GCC_C_LANGUAGE_STANDARD = gnu99;
533 | GCC_DYNAMIC_NO_PIC = NO;
534 | GCC_NO_COMMON_BLOCKS = YES;
535 | GCC_OPTIMIZATION_LEVEL = 0;
536 | GCC_PREPROCESSOR_DEFINITIONS = (
537 | "DEBUG=1",
538 | "$(inherited)",
539 | );
540 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
541 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
542 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
543 | GCC_WARN_UNDECLARED_SELECTOR = YES;
544 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
545 | GCC_WARN_UNUSED_FUNCTION = YES;
546 | GCC_WARN_UNUSED_VARIABLE = YES;
547 | IPHONEOS_DEPLOYMENT_TARGET = 12.4;
548 | LD_RUNPATH_SEARCH_PATHS = (
549 | /usr/lib/swift,
550 | "$(inherited)",
551 | );
552 | LIBRARY_SEARCH_PATHS = (
553 | "\"$(SDKROOT)/usr/lib/swift\"",
554 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
555 | "\"$(inherited)\"",
556 | );
557 | MTL_ENABLE_DEBUG_INFO = YES;
558 | ONLY_ACTIVE_ARCH = YES;
559 | OTHER_CFLAGS = "$(inherited)";
560 | OTHER_CPLUSPLUSFLAGS = (
561 | "$(OTHER_CFLAGS)",
562 | "-DFOLLY_NO_CONFIG",
563 | "-DFOLLY_MOBILE=1",
564 | "-DFOLLY_USE_LIBCPP=1",
565 | );
566 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
567 | SDKROOT = iphoneos;
568 | };
569 | name = Debug;
570 | };
571 | 83CBBA211A601CBA00E9B192 /* Release */ = {
572 | isa = XCBuildConfiguration;
573 | buildSettings = {
574 | ALWAYS_SEARCH_USER_PATHS = NO;
575 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
576 | CLANG_CXX_LANGUAGE_STANDARD = "c++17";
577 | CLANG_CXX_LIBRARY = "libc++";
578 | CLANG_ENABLE_MODULES = YES;
579 | CLANG_ENABLE_OBJC_ARC = YES;
580 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
581 | CLANG_WARN_BOOL_CONVERSION = YES;
582 | CLANG_WARN_COMMA = YES;
583 | CLANG_WARN_CONSTANT_CONVERSION = YES;
584 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
585 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
586 | CLANG_WARN_EMPTY_BODY = YES;
587 | CLANG_WARN_ENUM_CONVERSION = YES;
588 | CLANG_WARN_INFINITE_RECURSION = YES;
589 | CLANG_WARN_INT_CONVERSION = YES;
590 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
591 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
592 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
593 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
594 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
595 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
596 | CLANG_WARN_STRICT_PROTOTYPES = YES;
597 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
598 | CLANG_WARN_UNREACHABLE_CODE = YES;
599 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
600 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
601 | COPY_PHASE_STRIP = YES;
602 | ENABLE_NS_ASSERTIONS = NO;
603 | ENABLE_STRICT_OBJC_MSGSEND = YES;
604 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
605 | GCC_C_LANGUAGE_STANDARD = gnu99;
606 | GCC_NO_COMMON_BLOCKS = YES;
607 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
608 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
609 | GCC_WARN_UNDECLARED_SELECTOR = YES;
610 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
611 | GCC_WARN_UNUSED_FUNCTION = YES;
612 | GCC_WARN_UNUSED_VARIABLE = YES;
613 | IPHONEOS_DEPLOYMENT_TARGET = 12.4;
614 | LD_RUNPATH_SEARCH_PATHS = (
615 | /usr/lib/swift,
616 | "$(inherited)",
617 | );
618 | LIBRARY_SEARCH_PATHS = (
619 | "\"$(SDKROOT)/usr/lib/swift\"",
620 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
621 | "\"$(inherited)\"",
622 | );
623 | MTL_ENABLE_DEBUG_INFO = NO;
624 | OTHER_CFLAGS = "$(inherited)";
625 | OTHER_CPLUSPLUSFLAGS = (
626 | "$(OTHER_CFLAGS)",
627 | "-DFOLLY_NO_CONFIG",
628 | "-DFOLLY_MOBILE=1",
629 | "-DFOLLY_USE_LIBCPP=1",
630 | );
631 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
632 | SDKROOT = iphoneos;
633 | VALIDATE_PRODUCT = YES;
634 | };
635 | name = Release;
636 | };
637 | /* End XCBuildConfiguration section */
638 |
639 | /* Begin XCConfigurationList section */
640 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "ExampleTests" */ = {
641 | isa = XCConfigurationList;
642 | buildConfigurations = (
643 | 00E356F61AD99517003FC87E /* Debug */,
644 | 00E356F71AD99517003FC87E /* Release */,
645 | );
646 | defaultConfigurationIsVisible = 0;
647 | defaultConfigurationName = Release;
648 | };
649 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Example" */ = {
650 | isa = XCConfigurationList;
651 | buildConfigurations = (
652 | 13B07F941A680F5B00A75B9A /* Debug */,
653 | 13B07F951A680F5B00A75B9A /* Release */,
654 | );
655 | defaultConfigurationIsVisible = 0;
656 | defaultConfigurationName = Release;
657 | };
658 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Example" */ = {
659 | isa = XCConfigurationList;
660 | buildConfigurations = (
661 | 83CBBA201A601CBA00E9B192 /* Debug */,
662 | 83CBBA211A601CBA00E9B192 /* Release */,
663 | );
664 | defaultConfigurationIsVisible = 0;
665 | defaultConfigurationName = Release;
666 | };
667 | /* End XCConfigurationList section */
668 | };
669 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
670 | }
671 |
--------------------------------------------------------------------------------