Skip to content

Commit

Permalink
Move view config registry to shims
Browse files Browse the repository at this point in the history
This ensures that both Fabric and RN renderers share the same view config
registry since it is stateful.

I had to duplicate in the mocks for testing.
  • Loading branch information
sebmarkbage committed Apr 7, 2018
1 parent f947cdc commit ecc0422
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 18 deletions.
2 changes: 1 addition & 1 deletion packages/react-native-renderer/src/ReactFabricRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {
import {mountSafeCallback, warnForStyleProps} from './NativeMethodsMixinUtils';
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
import * as ReactNativeFrameScheduling from './ReactNativeFrameScheduling';
import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
import ReactFiberReconciler from 'react-reconciler';
import ReactNativeTagHandles from './ReactNativeTagHandles';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
accumulateTwoPhaseDispatches,
accumulateDirectDispatches,
} from 'events/EventPropagators';
import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
import SyntheticEvent from 'events/SyntheticEvent';
import invariant from 'fbjs/lib/invariant';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import invariant from 'fbjs/lib/invariant';
import UIManager from 'UIManager';
import deepFreezeAndThrowOnMutationInDev from 'deepFreezeAndThrowOnMutationInDev';

import * as ReactNativeViewConfigRegistry from './ReactNativeViewConfigRegistry';
import * as ReactNativeViewConfigRegistry from 'ReactNativeViewConfigRegistry';
import * as ReactNativeAttributePayload from './ReactNativeAttributePayload';
import {
precacheFiberNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@
*
* @flow
*/
'use strict';

import type {
ReactNativeBaseComponentViewConfig,
ViewConfigGetter,
} from './ReactNativeTypes';

import invariant from 'fbjs/lib/invariant';
const invariant = require('fbjs/lib/invariant');

// Event configs
export const customBubblingEventTypes = {};
export const customDirectEventTypes = {};
export const eventTypes = {};
const customBubblingEventTypes = {};
const customDirectEventTypes = {};
const eventTypes = {};

exports.customBubblingEventTypes = customBubblingEventTypes;
exports.customDirectEventTypes = customDirectEventTypes;
exports.eventTypes = eventTypes;

const viewConfigCallbacks = new Map();
const viewConfigs = new Map();
Expand Down Expand Up @@ -64,22 +69,22 @@ function processEventTypes(
* The callback is deferred until the view is actually rendered.
* This is done to avoid causing Prepack deopts.
*/
export function register(name: string, callback: ViewConfigGetter): string {
exports.register = function(name: string, callback: ViewConfigGetter): string {
invariant(
!viewConfigCallbacks.has(name),
'Tried to register two views with the same name %s',
name,
);
viewConfigCallbacks.set(name, callback);
return name;
}
};

/**
* Retrieves a config for the specified view.
* If this is the first time the view has been used,
* This configuration will be lazy-loaded from UIManager.
*/
export function get(name: string): ReactNativeBaseComponentViewConfig {
exports.get = function(name: string): ReactNativeBaseComponentViewConfig {
let viewConfig;
if (!viewConfigs.has(name)) {
const callback = viewConfigCallbacks.get(name);
Expand All @@ -97,4 +102,4 @@ export function get(name: string): ReactNativeBaseComponentViewConfig {
}
invariant(viewConfig, 'View config not found for name %s', name);
return viewConfig;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import type {ViewConfigGetter} from './ReactNativeTypes';

import {register} from './ReactNativeViewConfigRegistry';
import {register} from 'ReactNativeViewConfigRegistry';

/**
* Creates a renderable ReactNative host component.
Expand Down
17 changes: 11 additions & 6 deletions scripts/flow/react-native-host-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

/* eslint-disable */

import type {
ReactNativeBaseComponentViewConfig,
ViewConfigGetter,
} from 'react-native-renderer/src/ReactNativeTypes';

declare module 'deepDiffer' {
declare module.exports: (one: any, two: any) => boolean;
}
Expand Down Expand Up @@ -142,11 +147,11 @@ declare module 'BatchedBridge' {
declare function registerCallableModule(name: string, module: Object): void;
}

declare module 'CSComponent' {
declare type Element = any;
declare type Options<Instance> = any;
}
declare module 'ReactNativeViewConfigRegistry' {
declare var customBubblingEventTypes: Object;
declare var customDirectEventTypes: Object;
declare var eventTypes: Object;

declare module 'CSStatefulComponent' {
declare function CSStatefulComponent(spec: any): any;
declare function register(name: string, callback: ViewConfigGetter): string;
declare function get(name: string): ReactNativeBaseComponentViewConfig;
}
2 changes: 2 additions & 0 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ const bundles = [
'deepDiffer',
'deepFreezeAndThrowOnMutationInDev',
'flattenStyle',
'ReactNativeViewConfigRegistry',
],
},

Expand All @@ -150,6 +151,7 @@ const bundles = [
'deepDiffer',
'deepFreezeAndThrowOnMutationInDev',
'flattenStyle',
'ReactNativeViewConfigRegistry',
],
},

Expand Down
106 changes: 106 additions & 0 deletions scripts/rollup/shims/react-native/ReactNativeViewConfigRegistry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @providesModule ReactNativeViewConfigRegistry
* @flow
*/
'use strict';

import type {
ReactNativeBaseComponentViewConfig,
ViewConfigGetter,
} from './ReactNativeTypes';

const invariant = require('fbjs/lib/invariant');

// Event configs
const customBubblingEventTypes = {};
const customDirectEventTypes = {};
const eventTypes = {};

exports.customBubblingEventTypes = customBubblingEventTypes;
exports.customDirectEventTypes = customDirectEventTypes;
exports.eventTypes = eventTypes;

const viewConfigCallbacks = new Map();
const viewConfigs = new Map();

function processEventTypes(
viewConfig: ReactNativeBaseComponentViewConfig,
): void {
const {bubblingEventTypes, directEventTypes} = viewConfig;

if (__DEV__) {
if (bubblingEventTypes != null && directEventTypes != null) {
for (const topLevelType in directEventTypes) {
invariant(
bubblingEventTypes[topLevelType] == null,
'Event cannot be both direct and bubbling: %s',
topLevelType,
);
}
}
}

if (bubblingEventTypes != null) {
for (const topLevelType in bubblingEventTypes) {
if (customBubblingEventTypes[topLevelType] == null) {
eventTypes[topLevelType] = customBubblingEventTypes[topLevelType] =
bubblingEventTypes[topLevelType];
}
}
}

if (directEventTypes != null) {
for (const topLevelType in directEventTypes) {
if (customDirectEventTypes[topLevelType] == null) {
eventTypes[topLevelType] = customDirectEventTypes[topLevelType] =
directEventTypes[topLevelType];
}
}
}
}

/**
* Registers a native view/component by name.
* A callback is provided to load the view config from UIManager.
* The callback is deferred until the view is actually rendered.
* This is done to avoid causing Prepack deopts.
*/
exports.register = function(name: string, callback: ViewConfigGetter): string {
invariant(
!viewConfigCallbacks.has(name),
'Tried to register two views with the same name %s',
name,
);
viewConfigCallbacks.set(name, callback);
return name;
};

/**
* Retrieves a config for the specified view.
* If this is the first time the view has been used,
* This configuration will be lazy-loaded from UIManager.
*/
exports.get = function(name: string): ReactNativeBaseComponentViewConfig {
let viewConfig;
if (!viewConfigs.has(name)) {
const callback = viewConfigCallbacks.get(name);
invariant(
typeof callback === 'function',
'View config not found for name %s',
name,
);
viewConfigCallbacks.set(name, null);
viewConfig = callback();
processEventTypes(viewConfig);
viewConfigs.set(name, viewConfig);
} else {
viewConfig = viewConfigs.get(name);
}
invariant(viewConfig, 'View config not found for name %s', name);
return viewConfig;
};

0 comments on commit ecc0422

Please sign in to comment.