From d2e4beb9c77d736d87bf793137ad907e784fe1d5 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Thu, 26 Oct 2017 15:57:06 -0700 Subject: [PATCH 1/9] Port over initial stab at context --- example/test/context_test.dart | 18 +++++++ example/test/context_test.html | 14 +++++ example/test/react_test_components.dart | 38 ++++++++++++++ js_src/dart_helpers.js | 41 ++++++++++++--- lib/react.dart | 18 ++++++- lib/react.js | 41 ++++++++++++--- lib/react_client.dart | 69 +++++++++++++++++++++---- lib/react_client/react_interop.dart | 38 ++++++++++++-- lib/react_prod.js | 41 ++++++++++++--- lib/react_with_addons.js | 41 ++++++++++++--- lib/react_with_react_dom_prod.js | 41 ++++++++++++--- 11 files changed, 343 insertions(+), 57 deletions(-) create mode 100644 example/test/context_test.dart create mode 100644 example/test/context_test.html diff --git a/example/test/context_test.dart b/example/test/context_test.dart new file mode 100644 index 00000000..2b7673f1 --- /dev/null +++ b/example/test/context_test.dart @@ -0,0 +1,18 @@ +import 'dart:html'; + +import 'package:react/react_dom.dart' as react_dom; +import 'package:react/react_client.dart'; + +import 'react_test_components.dart'; + +void main() { + setClientConfiguration(); + + react_dom.render(contextComponent({}, + contextConsumerComponent({}), + ), querySelector('#content')); + + react_dom.render(contextComponent({}, + contextConsumerComponent({}), + ), querySelector('#content')); +} diff --git a/example/test/context_test.html b/example/test/context_test.html new file mode 100644 index 00000000..216fde50 --- /dev/null +++ b/example/test/context_test.html @@ -0,0 +1,14 @@ + + + + + context_test + + +
+ + + + + + diff --git a/example/test/react_test_components.dart b/example/test/react_test_components.dart index d1efb9ff..c377bf4c 100644 --- a/example/test/react_test_components.dart +++ b/example/test/react_test_components.dart @@ -152,3 +152,41 @@ class _MainComponent extends react.Component { } var mainComponent = react.registerComponent(() => new _MainComponent()); + +class _ContextComponent extends react.Component { + int _renderCount = 0; + + @override + Map getChildContext() => { + 'foo': 'bar', + 'renderCount': _renderCount + }; + + @override + Iterable get childContextKeys => const ['foo', 'renderCount']; + + render() { + _renderCount++; + + return react.ul({}, + 'ContextComponent.getChildContext(): ', + getChildContext().toString(), + props['children'] + ); + } +} +var contextComponent = react.registerComponent(() => new _ContextComponent()); + + +class _ContextConsumerComponent extends react.Component { + @override + Iterable get contextKeys => const ['foo', 'renderCount']; + + render() { + return react.ul({}, + 'ContextConsumerComponent.context: ', + context.toString(), + ); + } +} +var contextConsumerComponent = react.registerComponent(() => new _ContextConsumerComponent()); diff --git a/js_src/dart_helpers.js b/js_src/dart_helpers.js index 45939220..e9f24ff4 100644 --- a/js_src/dart_helpers.js +++ b/js_src/dart_helpers.js @@ -6,7 +6,32 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { + var childContextTypes; + var contextTypes; + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + childContextTypes[childContextKeys[i]] = React.PropTypes.any; + } + } + + if (contextKeys && contextKeys.length !== 0) { + contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + contextTypes[contextKeys[i]] = React.PropTypes.any; + } + } + return { + getChildContext: function() { + return dartInteropStatics.getChildContext(this.props.internal); + }, + childContextTypes: childContextTypes, + contextTypes: contextTypes, getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); return {}; @@ -17,17 +42,17 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentDidMount: function() { dartInteropStatics.handleComponentDidMount(this.dartComponent); }, - componentWillReceiveProps: function(nextProps) { - dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal); + componentWillReceiveProps: function(nextProps, nextContext) { + dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal, nextContext); }, - shouldComponentUpdate: function(nextProps, nextState) { - return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent); + shouldComponentUpdate: function(nextProps, nextState, nextContext) { + return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent, nextContext); }, - componentWillUpdate: function(nextProps, nextState) { - dartInteropStatics.handleComponentWillUpdate(this.dartComponent); + componentWillUpdate: function(nextProps, nextState, nextContext) { + dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); + componentDidUpdate: function(prevProps, prevState, prevContext) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react.dart b/lib/react.dart index e64b4808..09be85b8 100644 --- a/lib/react.dart +++ b/lib/react.dart @@ -10,6 +10,8 @@ import 'package:react/src/typedefs.dart'; /// Top-level ReactJS [Component class](https://facebook.github.io/react/docs/react-component.html) /// which provides the [ReactJS Component API](https://facebook.github.io/react/docs/react-component.html#reference) abstract class Component { + Map _context; + /// A private field that backs [props], which is exposed via getter/setter so /// it can be overridden in strong mode. /// @@ -37,6 +39,9 @@ abstract class Component { /// TODO: Switch back to a plain field once this issue is fixed. Ref _ref; + Map get context => _context; + set context(Map value) => _context = value; + /// ReactJS [Component] props. /// /// Related: [state] @@ -81,13 +86,18 @@ abstract class Component { /// Bind the value of input to [state[key]]. bind(key) => [state[key], (value) => setState({key: value})]; - initComponentInternal(props, _jsRedraw, [Ref ref, _jsThis]) { + initComponentInternal(context, props, _jsRedraw, [Ref ref, _jsThis]) { this._jsRedraw = _jsRedraw; this.ref = ref; this._jsThis = _jsThis; + _initContext(context); _initProps(props); } + _initContext(context) { + _context = new Map.from(context ?? {}); + } + _initProps(props) { this.props = new Map.from(props); this.nextProps = this.props; @@ -243,6 +253,12 @@ abstract class Component { /// See: void componentWillUnmount() {} + Map getChildContext() => {}; + + Iterable get childContextKeys => const []; + + Iterable get contextKeys => const []; + /// Invoked once before the `Component` is mounted. The return value will be used as the initial value of [state]. /// /// See: diff --git a/lib/react.js b/lib/react.js index 855306e4..7de53d01 100644 --- a/lib/react.js +++ b/lib/react.js @@ -4325,7 +4325,32 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { + var childContextTypes; + var contextTypes; + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + childContextTypes[childContextKeys[i]] = React.PropTypes.any; + } + } + + if (contextKeys && contextKeys.length !== 0) { + contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + contextTypes[contextKeys[i]] = React.PropTypes.any; + } + } + return { + getChildContext: function() { + return dartInteropStatics.getChildContext(this.props.internal); + }, + childContextTypes: childContextTypes, + contextTypes: contextTypes, getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); return {}; @@ -4336,17 +4361,17 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentDidMount: function() { dartInteropStatics.handleComponentDidMount(this.dartComponent); }, - componentWillReceiveProps: function(nextProps) { - dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal); + componentWillReceiveProps: function(nextProps, nextContext) { + dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal, nextContext); }, - shouldComponentUpdate: function(nextProps, nextState) { - return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent); + shouldComponentUpdate: function(nextProps, nextState, nextContext) { + return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent, nextContext); }, - componentWillUpdate: function(nextProps, nextState) { - dartInteropStatics.handleComponentWillUpdate(this.dartComponent); + componentWillUpdate: function(nextProps, nextState, nextContext) { + dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); + componentDidUpdate: function(prevProps, prevState, prevContext) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_client.dart b/lib/react_client.dart index 30c0e561..11805b71 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -11,6 +11,7 @@ import "dart:html"; import 'dart:js'; import "package:js/js.dart"; +import "package:js/js_util.dart" show newObject; import "package:react/react.dart"; import "package:react/react_client/js_interop_helpers.dart"; import 'package:react/react_client/react_interop.dart'; @@ -178,6 +179,24 @@ dynamic _convertArgsToChildren(List childrenArgs) { } } +@JS('Object.keys') +external List _objectKeys(Object object); + +_jsifyContext(Map context) { + var interopContext = newObject(); + context.forEach((key, value) { + setProperty(interopContext, key, value); + }); + + return interopContext; +} + +Map _unjsifyContext(interopContext) { + return new Map.fromIterable(_objectKeys(interopContext), value: (key) { + return getProperty(interopContext, key); + }); +} + /// The static methods that proxy JS component lifecycle methods to Dart components. final ReactDartInteropStatics _dartInteropStatics = (() { var zone = Zone.current; @@ -197,7 +216,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }; Component component = componentStatics.componentFactory() - ..initComponentInternal(internal.props, jsRedraw, getRef, jsThis) + ..initComponentInternal(_unjsifyContext(jsThis.context), internal.props, jsRedraw, getRef, jsThis) ..initStateInternal(); // Return the component so that the JS proxying component can store it, @@ -205,6 +224,21 @@ final ReactDartInteropStatics _dartInteropStatics = (() { return component; }); + InteropContext getChildContext(Component component) => zone.run(() { + var childContext = component.getChildContext(); + + assert(() { + var undeclaredKeys = childContext.keys.toSet().difference(component.childContextKeys.toSet()); + if (undeclaredKeys.isNotEmpty) { + throw new Exception('Context keys used in `getChildContext()` but not declared in `childContextKeys`: $undeclaredKeys'); + } + + return true; + }); + + return _jsifyContext(childContext); + }); + /// Wrapper for [Component.componentWillMount]. void handleComponentWillMount(Component component) => zone.run(() { component @@ -225,13 +259,19 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// 1. Update [Component.props] using the value stored to [Component.nextProps] /// in `componentWillReceiveProps`. /// 2. Update [Component.state] by calling [Component.transferComponentState] - void _afterPropsChange(Component component) { + /// 3. Update [Component.context] with the latest + void _afterPropsChange(Component component, InteropContext nextContext) { component.props = component.nextProps; // [1] component.transferComponentState(); // [2] + // [3] + component.context = _unjsifyContext(component.jsThis); } void _clearPrevState(Component component) { component.prevState = null; + + // [4] + component.context = _unjsifyContext(context); } void _callSetStateCallbacks(Component component) { @@ -248,7 +288,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { } /// Wrapper for [Component.componentWillReceiveProps]. - void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal) => zone.run(() { + void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, nextContext) => zone.run(() { var nextProps = _getNextProps(component, nextInternal); component ..nextProps = nextProps @@ -256,14 +296,14 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.shouldComponentUpdate]. - bool handleShouldComponentUpdate(Component component) => zone.run(() { + bool handleShouldComponentUpdate(Component component, nextContext) => zone.run(() { _callSetStateTransactionalCallbacks(component); if (component.shouldComponentUpdate(component.nextProps, component.nextState)) { return true; } else { // If component should not update, update props / transfer state because componentWillUpdate will not be called. - _afterPropsChange(component); + _afterPropsChange(component, nextContext); _callSetStateCallbacks(component); // Clear out prevState after it's done being used so it's not retained _clearPrevState(component); @@ -272,15 +312,15 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.componentWillUpdate]. - void handleComponentWillUpdate(Component component) => zone.run(() { + void handleComponentWillUpdate(Component component, nextContext) => zone.run(() { component.componentWillUpdate(component.nextProps, component.nextState); - _afterPropsChange(component); + _afterPropsChange(component, nextContext); }); /// Wrapper for [Component.componentDidUpdate]. /// /// Uses [prevState] which was transferred from [Component.nextState] in [componentWillUpdate]. - void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal) => zone.run(() { + void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, prevContext) => zone.run(() { var prevInternalProps = prevInternal.props; component.componentDidUpdate(prevInternalProps, component.prevState); _callSetStateCallbacks(component); @@ -304,6 +344,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { return new ReactDartInteropStatics( initComponent: allowInterop(initComponent), + getChildContext: allowInterop(getChildContext), handleComponentWillMount: allowInterop(handleComponentWillMount), handleComponentDidMount: allowInterop(handleComponentDidMount), handleComponentWillReceiveProps: allowInterop(handleComponentWillReceiveProps), @@ -318,18 +359,24 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// Returns a new [ReactComponentFactory] which produces a new JS /// [`ReactClass` component class](https://facebook.github.io/react/docs/top-level-api.html#react.createclass). ReactDartComponentFactoryProxy _registerComponent(ComponentFactory componentFactory, [Iterable skipMethods = const []]) { + var componentInstance = componentFactory(); var componentStatics = new ComponentStatics(componentFactory); + var jsConfig = new JsComponentConfig( + childContextKeys: componentInstance.childContextKeys, + contextKeys: componentInstance.contextKeys, + ); + /// Create the JS [`ReactClass` component class](https://facebook.github.io/react/docs/top-level-api.html#react.createclass) /// with custom JS lifecycle methods. var reactComponentClass = React.createClass( - createReactDartComponentClassConfig(_dartInteropStatics, componentStatics) - ..displayName = componentFactory().displayName + createReactDartComponentClassConfig(_dartInteropStatics, componentStatics, jsConfig) + ..displayName = componentInstance.displayName ); // Cache default props and store them on the ReactClass so they can be used // by ReactDartComponentFactoryProxy and externally. - final Map defaultProps = new Map.unmodifiable(componentFactory().getDefaultProps()); + final Map defaultProps = new Map.unmodifiable(componentInstance.getDefaultProps()); reactComponentClass.dartDefaultProps = defaultProps; return new ReactDartComponentFactoryProxy(reactComponentClass); diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart index b26188ab..1c0f910a 100644 --- a/lib/react_client/react_interop.dart +++ b/lib/react_client/react_interop.dart @@ -83,6 +83,8 @@ class ReactClassConfig { Function componentWillUpdate, Function componentDidUpdate, Function componentWillUnmount, + Function getChildContext, + Map childContextTypes, Function getDefaultProps, Function getInitialState, Function render @@ -122,6 +124,8 @@ class ReactElement { /// For composite components (react-dart or pure JS), this will be a [ReactClass]. external dynamic get type; + external InteropContext get context; + /// The props this element was created with. external InteropProps get props; @@ -146,6 +150,7 @@ class ReactElement { @anonymous class ReactComponent { external Component get dartComponent; + external InteropContext get context; external InteropProps get props; external get refs; external void setState(state, [callback]); @@ -158,6 +163,10 @@ class ReactComponent { // Interop internals // ---------------------------------------------------------------------------- +@JS() +@anonymous +class InteropContext {} + /// A JavaScript interop class representing a React JS `props` object. /// /// Used for storing/accessing [ReactDartComponentInternal] objects in @@ -183,6 +192,8 @@ class InteropProps { /// /// __For internal/advanced use only.__ class ReactDartComponentInternal { + Map context; + /// For a `ReactElement`, this is the initial props with defaults merged. /// /// For a `ReactComponent`, this is the props the component was last rendered with, @@ -213,15 +224,20 @@ void markChildrenValidated(List children) { /// [dartInteropStatics] and [componentStatics] internally to proxy between /// the JS and Dart component instances. @JS('_createReactDartComponentClassConfig') -external ReactClassConfig createReactDartComponentClassConfig(ReactDartInteropStatics dartInteropStatics, ComponentStatics componentStatics); +external ReactClassConfig createReactDartComponentClassConfig( + ReactDartInteropStatics dartInteropStatics, + ComponentStatics componentStatics, + [JsComponentConfig jsConfig] +); typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, ComponentStatics componentStatics); +typedef InteropContext _GetChildContext(Component component); typedef void _HandleComponentWillMount(Component component); typedef void _HandleComponentDidMount(Component component); -typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal); -typedef bool _HandleShouldComponentUpdate(Component component); -typedef void _HandleComponentWillUpdate(Component component); -typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal); +typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContext nextContext); +typedef bool _HandleShouldComponentUpdate(Component component, InteropContext nextContext); +typedef void _HandleComponentWillUpdate(Component component, InteropContext nextContext); +typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContext prevContext); typedef void _HandleComponentWillUnmount(Component component); typedef dynamic _HandleRender(Component component); @@ -231,6 +247,7 @@ typedef dynamic _HandleRender(Component component); class ReactDartInteropStatics { external factory ReactDartInteropStatics({ _InitComponent initComponent, + _GetChildContext getChildContext, _HandleComponentWillMount handleComponentWillMount, _HandleComponentDidMount handleComponentDidMount, _HandleComponentWillReceiveProps handleComponentWillReceiveProps, @@ -253,3 +270,14 @@ class ComponentStatics { ComponentStatics(this.componentFactory); } + +/// Additional configuration passed to [createReactDartComponentClassConfig] +/// that needs to be directly accessible by that JS code. +@JS() +@anonymous +class JsComponentConfig { + external factory JsComponentConfig({ + Iterable childContextKeys, + Iterable contextKeys, + }); +} diff --git a/lib/react_prod.js b/lib/react_prod.js index 2ce98061..a831a5e7 100644 --- a/lib/react_prod.js +++ b/lib/react_prod.js @@ -17,7 +17,32 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { + var childContextTypes; + var contextTypes; + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + childContextTypes[childContextKeys[i]] = React.PropTypes.any; + } + } + + if (contextKeys && contextKeys.length !== 0) { + contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + contextTypes[contextKeys[i]] = React.PropTypes.any; + } + } + return { + getChildContext: function() { + return dartInteropStatics.getChildContext(this.props.internal); + }, + childContextTypes: childContextTypes, + contextTypes: contextTypes, getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); return {}; @@ -28,17 +53,17 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentDidMount: function() { dartInteropStatics.handleComponentDidMount(this.dartComponent); }, - componentWillReceiveProps: function(nextProps) { - dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal); + componentWillReceiveProps: function(nextProps, nextContext) { + dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal, nextContext); }, - shouldComponentUpdate: function(nextProps, nextState) { - return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent); + shouldComponentUpdate: function(nextProps, nextState, nextContext) { + return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent, nextContext); }, - componentWillUpdate: function(nextProps, nextState) { - dartInteropStatics.handleComponentWillUpdate(this.dartComponent); + componentWillUpdate: function(nextProps, nextState, nextContext) { + dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); + componentDidUpdate: function(prevProps, prevState, prevContext) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_with_addons.js b/lib/react_with_addons.js index ef122fab..4e821374 100644 --- a/lib/react_with_addons.js +++ b/lib/react_with_addons.js @@ -5966,7 +5966,32 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { + var childContextTypes; + var contextTypes; + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + childContextTypes[childContextKeys[i]] = React.PropTypes.any; + } + } + + if (contextKeys && contextKeys.length !== 0) { + contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + contextTypes[contextKeys[i]] = React.PropTypes.any; + } + } + return { + getChildContext: function() { + return dartInteropStatics.getChildContext(this.props.internal); + }, + childContextTypes: childContextTypes, + contextTypes: contextTypes, getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); return {}; @@ -5977,17 +6002,17 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentDidMount: function() { dartInteropStatics.handleComponentDidMount(this.dartComponent); }, - componentWillReceiveProps: function(nextProps) { - dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal); + componentWillReceiveProps: function(nextProps, nextContext) { + dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal, nextContext); }, - shouldComponentUpdate: function(nextProps, nextState) { - return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent); + shouldComponentUpdate: function(nextProps, nextState, nextContext) { + return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent, nextContext); }, - componentWillUpdate: function(nextProps, nextState) { - dartInteropStatics.handleComponentWillUpdate(this.dartComponent); + componentWillUpdate: function(nextProps, nextState, nextContext) { + dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); + componentDidUpdate: function(prevProps, prevState, prevContext) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_with_react_dom_prod.js b/lib/react_with_react_dom_prod.js index 82e9ddd3..595bb0e7 100644 --- a/lib/react_with_react_dom_prod.js +++ b/lib/react_with_react_dom_prod.js @@ -17,7 +17,32 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { + var childContextTypes; + var contextTypes; + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + childContextTypes[childContextKeys[i]] = React.PropTypes.any; + } + } + + if (contextKeys && contextKeys.length !== 0) { + contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + contextTypes[contextKeys[i]] = React.PropTypes.any; + } + } + return { + getChildContext: function() { + return dartInteropStatics.getChildContext(this.props.internal); + }, + childContextTypes: childContextTypes, + contextTypes: contextTypes, getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); return {}; @@ -28,17 +53,17 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentDidMount: function() { dartInteropStatics.handleComponentDidMount(this.dartComponent); }, - componentWillReceiveProps: function(nextProps) { - dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal); + componentWillReceiveProps: function(nextProps, nextContext) { + dartInteropStatics.handleComponentWillReceiveProps(this.dartComponent, nextProps.internal, nextContext); }, - shouldComponentUpdate: function(nextProps, nextState) { - return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent); + shouldComponentUpdate: function(nextProps, nextState, nextContext) { + return dartInteropStatics.handleShouldComponentUpdate(this.dartComponent, nextContext); }, - componentWillUpdate: function(nextProps, nextState) { - dartInteropStatics.handleComponentWillUpdate(this.dartComponent); + componentWillUpdate: function(nextProps, nextState, nextContext) { + dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); + componentDidUpdate: function(prevProps, prevState, prevContext) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); From 3ec943613d7a5f32a3131c63fe0f5cff40f0ad7d Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Thu, 26 Oct 2017 15:57:33 -0700 Subject: [PATCH 2/9] Fix breaking change to initComponentInternal --- lib/react.dart | 2 +- lib/react_client.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/react.dart b/lib/react.dart index 09be85b8..6f861537 100644 --- a/lib/react.dart +++ b/lib/react.dart @@ -86,7 +86,7 @@ abstract class Component { /// Bind the value of input to [state[key]]. bind(key) => [state[key], (value) => setState({key: value})]; - initComponentInternal(context, props, _jsRedraw, [Ref ref, _jsThis]) { + initComponentInternal(props, _jsRedraw, [Ref ref, _jsThis, context]) { this._jsRedraw = _jsRedraw; this.ref = ref; this._jsThis = _jsThis; diff --git a/lib/react_client.dart b/lib/react_client.dart index 11805b71..8493dd4d 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -216,7 +216,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }; Component component = componentStatics.componentFactory() - ..initComponentInternal(_unjsifyContext(jsThis.context), internal.props, jsRedraw, getRef, jsThis) + ..initComponentInternal(internal.props, jsRedraw, getRef, jsThis, _unjsifyContext(jsThis.context)) ..initStateInternal(); // Return the component so that the JS proxying component can store it, From e1a44b0801e498471fc7aba29d710a014626625f Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 08:50:44 -0700 Subject: [PATCH 3/9] Use internal pattern for individual context keys --- js_src/dart_helpers.js | 2 +- lib/react_client.dart | 43 ++++++++++------------------- lib/react_client/react_interop.dart | 16 +++++++---- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/js_src/dart_helpers.js b/js_src/dart_helpers.js index e9f24ff4..33310fcb 100644 --- a/js_src/dart_helpers.js +++ b/js_src/dart_helpers.js @@ -33,7 +33,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati childContextTypes: childContextTypes, contextTypes: contextTypes, getInitialState: function() { - this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); + this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; }, componentWillMount: function() { diff --git a/lib/react_client.dart b/lib/react_client.dart index 8493dd4d..b4048278 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -11,7 +11,6 @@ import "dart:html"; import 'dart:js'; import "package:js/js.dart"; -import "package:js/js_util.dart" show newObject; import "package:react/react.dart"; import "package:react/react_client/js_interop_helpers.dart"; import 'package:react/react_client/react_interop.dart'; @@ -182,18 +181,20 @@ dynamic _convertArgsToChildren(List childrenArgs) { @JS('Object.keys') external List _objectKeys(Object object); -_jsifyContext(Map context) { - var interopContext = newObject(); +InteropContext _jsifyContext(Map context) { + var interopContext = new InteropContext(); context.forEach((key, value) { - setProperty(interopContext, key, value); + setProperty(interopContext, key, new ReactDartContextInternal(value)); }); return interopContext; } -Map _unjsifyContext(interopContext) { +Map _unjsifyContext(InteropContext interopContext) { + // TODO consider using `contextKeys` for this if perf of objectKeys is bad. return new Map.fromIterable(_objectKeys(interopContext), value: (key) { - return getProperty(interopContext, key); + ReactDartContextInternal internal = getProperty(interopContext, key); + return internal.value; }); } @@ -202,7 +203,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { var zone = Zone.current; /// Wrapper for [Component.getInitialState]. - Component initComponent(ReactComponent jsThis, ReactDartComponentInternal internal, ComponentStatics componentStatics) => zone.run(() { + Component initComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContext context, ComponentStatics componentStatics) => zone.run(() { void jsRedraw() { jsThis.setState(emptyJsMap); } @@ -216,7 +217,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }; Component component = componentStatics.componentFactory() - ..initComponentInternal(internal.props, jsRedraw, getRef, jsThis, _unjsifyContext(jsThis.context)) + ..initComponentInternal(internal.props, jsRedraw, getRef, jsThis, _unjsifyContext(context)) ..initStateInternal(); // Return the component so that the JS proxying component can store it, @@ -225,18 +226,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); InteropContext getChildContext(Component component) => zone.run(() { - var childContext = component.getChildContext(); - - assert(() { - var undeclaredKeys = childContext.keys.toSet().difference(component.childContextKeys.toSet()); - if (undeclaredKeys.isNotEmpty) { - throw new Exception('Context keys used in `getChildContext()` but not declared in `childContextKeys`: $undeclaredKeys'); - } - - return true; - }); - - return _jsifyContext(childContext); + return _jsifyContext(component.getChildContext()); }); /// Wrapper for [Component.componentWillMount]. @@ -264,14 +254,11 @@ final ReactDartInteropStatics _dartInteropStatics = (() { component.props = component.nextProps; // [1] component.transferComponentState(); // [2] // [3] - component.context = _unjsifyContext(component.jsThis); + component.context = _unjsifyContext(nextContext); } void _clearPrevState(Component component) { component.prevState = null; - - // [4] - component.context = _unjsifyContext(context); } void _callSetStateCallbacks(Component component) { @@ -288,7 +275,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { } /// Wrapper for [Component.componentWillReceiveProps]. - void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, nextContext) => zone.run(() { + void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContext nextContext) => zone.run(() { var nextProps = _getNextProps(component, nextInternal); component ..nextProps = nextProps @@ -296,7 +283,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.shouldComponentUpdate]. - bool handleShouldComponentUpdate(Component component, nextContext) => zone.run(() { + bool handleShouldComponentUpdate(Component component, InteropContext nextContext) => zone.run(() { _callSetStateTransactionalCallbacks(component); if (component.shouldComponentUpdate(component.nextProps, component.nextState)) { @@ -312,7 +299,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.componentWillUpdate]. - void handleComponentWillUpdate(Component component, nextContext) => zone.run(() { + void handleComponentWillUpdate(Component component, InteropContext nextContext) => zone.run(() { component.componentWillUpdate(component.nextProps, component.nextState); _afterPropsChange(component, nextContext); }); @@ -320,7 +307,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// Wrapper for [Component.componentDidUpdate]. /// /// Uses [prevState] which was transferred from [Component.nextState] in [componentWillUpdate]. - void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, prevContext) => zone.run(() { + void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContext prevContext) => zone.run(() { var prevInternalProps = prevInternal.props; component.componentDidUpdate(prevInternalProps, component.prevState); _callSetStateCallbacks(component); diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart index 1c0f910a..71ad989f 100644 --- a/lib/react_client/react_interop.dart +++ b/lib/react_client/react_interop.dart @@ -124,8 +124,6 @@ class ReactElement { /// For composite components (react-dart or pure JS), this will be a [ReactClass]. external dynamic get type; - external InteropContext get context; - /// The props this element was created with. external InteropProps get props; @@ -165,7 +163,9 @@ class ReactComponent { @JS() @anonymous -class InteropContext {} +class InteropContext { + external factory InteropContext(); +} /// A JavaScript interop class representing a React JS `props` object. /// @@ -192,8 +192,6 @@ class InteropProps { /// /// __For internal/advanced use only.__ class ReactDartComponentInternal { - Map context; - /// For a `ReactElement`, this is the initial props with defaults merged. /// /// For a `ReactComponent`, this is the props the component was last rendered with, @@ -201,6 +199,12 @@ class ReactDartComponentInternal { Map props; } +class ReactDartContextInternal { + final dynamic value; + + ReactDartContextInternal(this.value); +} + /// Marks [child] as validated, as if it were passed into [React.createElement] /// as a variadic child. /// @@ -230,7 +234,7 @@ external ReactClassConfig createReactDartComponentClassConfig( [JsComponentConfig jsConfig] ); -typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, ComponentStatics componentStatics); +typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContext context, ComponentStatics componentStatics); typedef InteropContext _GetChildContext(Component component); typedef void _HandleComponentWillMount(Component component); typedef void _HandleComponentDidMount(Component component); From 27fea39f29160c0b103307a2fa8dfa1027ef2902 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 08:55:44 -0700 Subject: [PATCH 4/9] Fix JS, conditionally declare context pieces on config --- js_src/dart_helpers.js | 57 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/js_src/dart_helpers.js b/js_src/dart_helpers.js index 33310fcb..14fdb3b9 100644 --- a/js_src/dart_helpers.js +++ b/js_src/dart_helpers.js @@ -5,33 +5,8 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } -function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { - var childContextTypes; - var contextTypes; - - var childContextKeys = jsConfig && jsConfig.childContextKeys; - var contextKeys = jsConfig && jsConfig.contextKeys; - - if (childContextKeys && childContextKeys.length !== 0) { - childContextTypes = {}; - for (var i = 0; i < childContextKeys.length; i++) { - childContextTypes[childContextKeys[i]] = React.PropTypes.any; - } - } - - if (contextKeys && contextKeys.length !== 0) { - contextTypes = {}; - for (var i = 0; i < contextKeys.length; i++) { - contextTypes[contextKeys[i]] = React.PropTypes.any; - } - } - - return { - getChildContext: function() { - return dartInteropStatics.getChildContext(this.props.internal); - }, - childContextTypes: childContextTypes, - contextTypes: contextTypes, +function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics, jsConfig) { + var config = { getInitialState: function() { this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; @@ -61,6 +36,34 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati return dartInteropStatics.handleRender(this.dartComponent); } }; + + // React limits the accessible context entries + // to the keys specified in childContextTypes/contextTypes. + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + config.childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + config.childContextTypes[childContextKeys[i]] = React.PropTypes.object; + } + + // Only declare this when `hasChildContext` is true to avoid unnecessarily + // creating interop context objects for components that won't use it. + config.getChildContext = function() { + return dartInteropStatics.getChildContext(this.dartComponent); + }; + } + + if (contextKeys && contextKeys.length !== 0) { + config.contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + config.contextTypes[contextKeys[i]] = React.PropTypes.object; + } + } + + return config; } function _markChildValidated(child) { From 2408a099b87e8172afd88934904523a8fbc49aa5 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 08:57:04 -0700 Subject: [PATCH 5/9] Generate JS files --- lib/react.js | 59 +++++++++++++++++--------------- lib/react_prod.js | 59 +++++++++++++++++--------------- lib/react_with_addons.js | 59 +++++++++++++++++--------------- lib/react_with_react_dom_prod.js | 59 +++++++++++++++++--------------- 4 files changed, 124 insertions(+), 112 deletions(-) diff --git a/lib/react.js b/lib/react.js index 7de53d01..37fa6bee 100644 --- a/lib/react.js +++ b/lib/react.js @@ -4324,35 +4324,10 @@ module.exports = ReactPropTypesSecret; function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } -function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { - var childContextTypes; - var contextTypes; - - var childContextKeys = jsConfig && jsConfig.childContextKeys; - var contextKeys = jsConfig && jsConfig.contextKeys; - - if (childContextKeys && childContextKeys.length !== 0) { - childContextTypes = {}; - for (var i = 0; i < childContextKeys.length; i++) { - childContextTypes[childContextKeys[i]] = React.PropTypes.any; - } - } - - if (contextKeys && contextKeys.length !== 0) { - contextTypes = {}; - for (var i = 0; i < contextKeys.length; i++) { - contextTypes[contextKeys[i]] = React.PropTypes.any; - } - } - - return { - getChildContext: function() { - return dartInteropStatics.getChildContext(this.props.internal); - }, - childContextTypes: childContextTypes, - contextTypes: contextTypes, +function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics, jsConfig) { + var config = { getInitialState: function() { - this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); + this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; }, componentWillMount: function() { @@ -4380,6 +4355,34 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati return dartInteropStatics.handleRender(this.dartComponent); } }; + + // React limits the accessible context entries + // to the keys specified in childContextTypes/contextTypes. + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + config.childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + config.childContextTypes[childContextKeys[i]] = React.PropTypes.object; + } + + // Only declare this when `hasChildContext` is true to avoid unnecessarily + // creating interop context objects for components that won't use it. + config.getChildContext = function() { + return dartInteropStatics.getChildContext(this.dartComponent); + }; + } + + if (contextKeys && contextKeys.length !== 0) { + config.contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + config.contextTypes[contextKeys[i]] = React.PropTypes.object; + } + } + + return config; } function _markChildValidated(child) { diff --git a/lib/react_prod.js b/lib/react_prod.js index a831a5e7..48bdc81c 100644 --- a/lib/react_prod.js +++ b/lib/react_prod.js @@ -16,35 +16,10 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } -function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { - var childContextTypes; - var contextTypes; - - var childContextKeys = jsConfig && jsConfig.childContextKeys; - var contextKeys = jsConfig && jsConfig.contextKeys; - - if (childContextKeys && childContextKeys.length !== 0) { - childContextTypes = {}; - for (var i = 0; i < childContextKeys.length; i++) { - childContextTypes[childContextKeys[i]] = React.PropTypes.any; - } - } - - if (contextKeys && contextKeys.length !== 0) { - contextTypes = {}; - for (var i = 0; i < contextKeys.length; i++) { - contextTypes[contextKeys[i]] = React.PropTypes.any; - } - } - - return { - getChildContext: function() { - return dartInteropStatics.getChildContext(this.props.internal); - }, - childContextTypes: childContextTypes, - contextTypes: contextTypes, +function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics, jsConfig) { + var config = { getInitialState: function() { - this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); + this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; }, componentWillMount: function() { @@ -72,6 +47,34 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati return dartInteropStatics.handleRender(this.dartComponent); } }; + + // React limits the accessible context entries + // to the keys specified in childContextTypes/contextTypes. + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + config.childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + config.childContextTypes[childContextKeys[i]] = React.PropTypes.object; + } + + // Only declare this when `hasChildContext` is true to avoid unnecessarily + // creating interop context objects for components that won't use it. + config.getChildContext = function() { + return dartInteropStatics.getChildContext(this.dartComponent); + }; + } + + if (contextKeys && contextKeys.length !== 0) { + config.contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + config.contextTypes[contextKeys[i]] = React.PropTypes.object; + } + } + + return config; } function _markChildValidated(child) { diff --git a/lib/react_with_addons.js b/lib/react_with_addons.js index 4e821374..d00ac10e 100644 --- a/lib/react_with_addons.js +++ b/lib/react_with_addons.js @@ -5965,35 +5965,10 @@ module.exports = ReactPropTypesSecret; function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } -function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { - var childContextTypes; - var contextTypes; - - var childContextKeys = jsConfig && jsConfig.childContextKeys; - var contextKeys = jsConfig && jsConfig.contextKeys; - - if (childContextKeys && childContextKeys.length !== 0) { - childContextTypes = {}; - for (var i = 0; i < childContextKeys.length; i++) { - childContextTypes[childContextKeys[i]] = React.PropTypes.any; - } - } - - if (contextKeys && contextKeys.length !== 0) { - contextTypes = {}; - for (var i = 0; i < contextKeys.length; i++) { - contextTypes[contextKeys[i]] = React.PropTypes.any; - } - } - - return { - getChildContext: function() { - return dartInteropStatics.getChildContext(this.props.internal); - }, - childContextTypes: childContextTypes, - contextTypes: contextTypes, +function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics, jsConfig) { + var config = { getInitialState: function() { - this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); + this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; }, componentWillMount: function() { @@ -6021,6 +5996,34 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati return dartInteropStatics.handleRender(this.dartComponent); } }; + + // React limits the accessible context entries + // to the keys specified in childContextTypes/contextTypes. + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + config.childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + config.childContextTypes[childContextKeys[i]] = React.PropTypes.object; + } + + // Only declare this when `hasChildContext` is true to avoid unnecessarily + // creating interop context objects for components that won't use it. + config.getChildContext = function() { + return dartInteropStatics.getChildContext(this.dartComponent); + }; + } + + if (contextKeys && contextKeys.length !== 0) { + config.contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + config.contextTypes[contextKeys[i]] = React.PropTypes.object; + } + } + + return config; } function _markChildValidated(child) { diff --git a/lib/react_with_react_dom_prod.js b/lib/react_with_react_dom_prod.js index 595bb0e7..5083821f 100644 --- a/lib/react_with_react_dom_prod.js +++ b/lib/react_with_react_dom_prod.js @@ -16,35 +16,10 @@ function _getProperty(obj, key) { return obj[key]; } function _setProperty(obj, key, value) { return obj[key] = value; } -function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics) { - var childContextTypes; - var contextTypes; - - var childContextKeys = jsConfig && jsConfig.childContextKeys; - var contextKeys = jsConfig && jsConfig.contextKeys; - - if (childContextKeys && childContextKeys.length !== 0) { - childContextTypes = {}; - for (var i = 0; i < childContextKeys.length; i++) { - childContextTypes[childContextKeys[i]] = React.PropTypes.any; - } - } - - if (contextKeys && contextKeys.length !== 0) { - contextTypes = {}; - for (var i = 0; i < contextKeys.length; i++) { - contextTypes[contextKeys[i]] = React.PropTypes.any; - } - } - - return { - getChildContext: function() { - return dartInteropStatics.getChildContext(this.props.internal); - }, - childContextTypes: childContextTypes, - contextTypes: contextTypes, +function _createReactDartComponentClassConfig(dartInteropStatics, componentStatics, jsConfig) { + var config = { getInitialState: function() { - this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, componentStatics); + this.dartComponent = dartInteropStatics.initComponent(this, this.props.internal, this.context, componentStatics); return {}; }, componentWillMount: function() { @@ -72,6 +47,34 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati return dartInteropStatics.handleRender(this.dartComponent); } }; + + // React limits the accessible context entries + // to the keys specified in childContextTypes/contextTypes. + + var childContextKeys = jsConfig && jsConfig.childContextKeys; + var contextKeys = jsConfig && jsConfig.contextKeys; + + if (childContextKeys && childContextKeys.length !== 0) { + config.childContextTypes = {}; + for (var i = 0; i < childContextKeys.length; i++) { + config.childContextTypes[childContextKeys[i]] = React.PropTypes.object; + } + + // Only declare this when `hasChildContext` is true to avoid unnecessarily + // creating interop context objects for components that won't use it. + config.getChildContext = function() { + return dartInteropStatics.getChildContext(this.dartComponent); + }; + } + + if (contextKeys && contextKeys.length !== 0) { + config.contextTypes = {}; + for (var i = 0; i < contextKeys.length; i++) { + config.contextTypes[contextKeys[i]] = React.PropTypes.object; + } + } + + return config; } function _markChildValidated(child) { From f77241952588906be639d6111e8fd129494a56c2 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 09:16:51 -0700 Subject: [PATCH 6/9] Cleanup, naming, docs --- example/test/react_test_components.dart | 2 +- lib/react.dart | 14 +++++++++++- lib/react_client.dart | 20 ++++++++--------- lib/react_client/react_interop.dart | 30 ++++++++++++++++--------- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/example/test/react_test_components.dart b/example/test/react_test_components.dart index c377bf4c..2e7d6021 100644 --- a/example/test/react_test_components.dart +++ b/example/test/react_test_components.dart @@ -157,7 +157,7 @@ class _ContextComponent extends react.Component { int _renderCount = 0; @override - Map getChildContext() => { + Map getChildContext() => { 'foo': 'bar', 'renderCount': _renderCount }; diff --git a/lib/react.dart b/lib/react.dart index 6f861537..5ceef3fb 100644 --- a/lib/react.dart +++ b/lib/react.dart @@ -39,6 +39,9 @@ abstract class Component { /// TODO: Switch back to a plain field once this issue is fixed. Ref _ref; + /// The React context map of this component, passed down from its ancestors' [getChildContext] value. + /// + /// Only keys declared in this component's [contextKeys] will be present. Map get context => _context; set context(Map value) => _context = value; @@ -253,10 +256,19 @@ abstract class Component { /// See: void componentWillUnmount() {} - Map getChildContext() => {}; + /// Returns a Map of context to be passed to descendant components. + /// + /// Only keys present in [childContextKeys] will be used; all others will be ignored. + Map getChildContext() => const {}; + /// The keys this component uses in its child context map (returned by [getChildContext]). + /// + /// __This method is called only once, upon component registration.__ Iterable get childContextKeys => const []; + /// The keys of context used by this component. + /// + /// __This method is called only once, upon component registration.__ Iterable get contextKeys => const []; /// Invoked once before the `Component` is mounted. The return value will be used as the initial value of [state]. diff --git a/lib/react_client.dart b/lib/react_client.dart index b4048278..567ae8f0 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -181,8 +181,8 @@ dynamic _convertArgsToChildren(List childrenArgs) { @JS('Object.keys') external List _objectKeys(Object object); -InteropContext _jsifyContext(Map context) { - var interopContext = new InteropContext(); +InteropContextValue _jsifyContext(Map context) { + var interopContext = new InteropContextValue(); context.forEach((key, value) { setProperty(interopContext, key, new ReactDartContextInternal(value)); }); @@ -190,7 +190,7 @@ InteropContext _jsifyContext(Map context) { return interopContext; } -Map _unjsifyContext(InteropContext interopContext) { +Map _unjsifyContext(InteropContextValue interopContext) { // TODO consider using `contextKeys` for this if perf of objectKeys is bad. return new Map.fromIterable(_objectKeys(interopContext), value: (key) { ReactDartContextInternal internal = getProperty(interopContext, key); @@ -203,7 +203,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { var zone = Zone.current; /// Wrapper for [Component.getInitialState]. - Component initComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContext context, ComponentStatics componentStatics) => zone.run(() { + Component initComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContextValue context, ComponentStatics componentStatics) => zone.run(() { void jsRedraw() { jsThis.setState(emptyJsMap); } @@ -225,7 +225,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { return component; }); - InteropContext getChildContext(Component component) => zone.run(() { + InteropContextValue getChildContext(Component component) => zone.run(() { return _jsifyContext(component.getChildContext()); }); @@ -250,7 +250,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// in `componentWillReceiveProps`. /// 2. Update [Component.state] by calling [Component.transferComponentState] /// 3. Update [Component.context] with the latest - void _afterPropsChange(Component component, InteropContext nextContext) { + void _afterPropsChange(Component component, InteropContextValue nextContext) { component.props = component.nextProps; // [1] component.transferComponentState(); // [2] // [3] @@ -275,7 +275,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { } /// Wrapper for [Component.componentWillReceiveProps]. - void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContext nextContext) => zone.run(() { + void handleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContextValue nextContext) => zone.run(() { var nextProps = _getNextProps(component, nextInternal); component ..nextProps = nextProps @@ -283,7 +283,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.shouldComponentUpdate]. - bool handleShouldComponentUpdate(Component component, InteropContext nextContext) => zone.run(() { + bool handleShouldComponentUpdate(Component component, InteropContextValue nextContext) => zone.run(() { _callSetStateTransactionalCallbacks(component); if (component.shouldComponentUpdate(component.nextProps, component.nextState)) { @@ -299,7 +299,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { }); /// Wrapper for [Component.componentWillUpdate]. - void handleComponentWillUpdate(Component component, InteropContext nextContext) => zone.run(() { + void handleComponentWillUpdate(Component component, InteropContextValue nextContext) => zone.run(() { component.componentWillUpdate(component.nextProps, component.nextState); _afterPropsChange(component, nextContext); }); @@ -307,7 +307,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// Wrapper for [Component.componentDidUpdate]. /// /// Uses [prevState] which was transferred from [Component.nextState] in [componentWillUpdate]. - void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContext prevContext) => zone.run(() { + void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContextValue prevContext) => zone.run(() { var prevInternalProps = prevInternal.props; component.componentDidUpdate(prevInternalProps, component.prevState); _callSetStateCallbacks(component); diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart index 71ad989f..092c86fe 100644 --- a/lib/react_client/react_interop.dart +++ b/lib/react_client/react_interop.dart @@ -148,7 +148,6 @@ class ReactElement { @anonymous class ReactComponent { external Component get dartComponent; - external InteropContext get context; external InteropProps get props; external get refs; external void setState(state, [callback]); @@ -161,10 +160,16 @@ class ReactComponent { // Interop internals // ---------------------------------------------------------------------------- +/// A JavaScript interop class representing a value in a React JS `context` object. +/// +/// Used for storing/accessing Dart [ReactDartContextInternal] objects in `context` +/// in a way that's opaque to the JS, and avoids the need to use dart2js interceptors. +/// +/// __For internal/advanced use only.__ @JS() @anonymous -class InteropContext { - external factory InteropContext(); +class InteropContextValue { + external factory InteropContextValue(); } /// A JavaScript interop class representing a React JS `props` object. @@ -187,8 +192,7 @@ class InteropProps { external factory InteropProps({ReactDartComponentInternal internal, String key, dynamic ref}); } -/// Internal react-dart information used to proxy React JS lifecycle to Dart -/// [Component] instances. +/// A Dart object that stores . /// /// __For internal/advanced use only.__ class ReactDartComponentInternal { @@ -199,6 +203,10 @@ class ReactDartComponentInternal { Map props; } +/// Internal react-dart information used to proxy React JS lifecycle to Dart +/// [Component] instances. +/// +/// __For internal/advanced use only.__ class ReactDartContextInternal { final dynamic value; @@ -234,14 +242,14 @@ external ReactClassConfig createReactDartComponentClassConfig( [JsComponentConfig jsConfig] ); -typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContext context, ComponentStatics componentStatics); -typedef InteropContext _GetChildContext(Component component); +typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContextValue context, ComponentStatics componentStatics); +typedef InteropContextValue _GetChildContext(Component component); typedef void _HandleComponentWillMount(Component component); typedef void _HandleComponentDidMount(Component component); -typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContext nextContext); -typedef bool _HandleShouldComponentUpdate(Component component, InteropContext nextContext); -typedef void _HandleComponentWillUpdate(Component component, InteropContext nextContext); -typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContext prevContext); +typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContextValue nextContext); +typedef bool _HandleShouldComponentUpdate(Component component, InteropContextValue nextContext); +typedef void _HandleComponentWillUpdate(Component component, InteropContextValue nextContext); +typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContextValue prevContext); typedef void _HandleComponentWillUnmount(Component component); typedef dynamic _HandleRender(Component component); From bb04f637ff85439d42c33976f2c8b4555b54e14d Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 09:19:38 -0700 Subject: [PATCH 7/9] Ignore prevContext since it isn't supported in React 16 --- js_src/dart_helpers.js | 4 ++-- lib/react_client.dart | 2 +- lib/react_client/react_interop.dart | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/js_src/dart_helpers.js b/js_src/dart_helpers.js index 14fdb3b9..e65669b9 100644 --- a/js_src/dart_helpers.js +++ b/js_src/dart_helpers.js @@ -26,8 +26,8 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentWillUpdate: function(nextProps, nextState, nextContext) { dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState, prevContext) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); + componentDidUpdate: function(prevProps, prevState) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_client.dart b/lib/react_client.dart index 567ae8f0..5f2c0f8f 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -307,7 +307,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { /// Wrapper for [Component.componentDidUpdate]. /// /// Uses [prevState] which was transferred from [Component.nextState] in [componentWillUpdate]. - void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContextValue prevContext) => zone.run(() { + void handleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal) => zone.run(() { var prevInternalProps = prevInternal.props; component.componentDidUpdate(prevInternalProps, component.prevState); _callSetStateCallbacks(component); diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart index 092c86fe..0baab30d 100644 --- a/lib/react_client/react_interop.dart +++ b/lib/react_client/react_interop.dart @@ -249,7 +249,8 @@ typedef void _HandleComponentDidMount(Component component); typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContextValue nextContext); typedef bool _HandleShouldComponentUpdate(Component component, InteropContextValue nextContext); typedef void _HandleComponentWillUpdate(Component component, InteropContextValue nextContext); -typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal, InteropContextValue prevContext); +// Ignore prevContext in componentDidUpdate, since it's not supported in React 16 +typedef void _HandleComponentDidUpdate(Component component, ReactDartComponentInternal prevInternal); typedef void _HandleComponentWillUnmount(Component component); typedef dynamic _HandleRender(Component component); From b80ac0a48e99c24b4c1bc36d6e53c63d8333e137 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 09:20:37 -0700 Subject: [PATCH 8/9] Generate JS --- lib/react.js | 4 ++-- lib/react_prod.js | 4 ++-- lib/react_with_addons.js | 4 ++-- lib/react_with_react_dom_prod.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/react.js b/lib/react.js index 37fa6bee..1651a0da 100644 --- a/lib/react.js +++ b/lib/react.js @@ -4345,8 +4345,8 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentWillUpdate: function(nextProps, nextState, nextContext) { dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState, prevContext) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); + componentDidUpdate: function(prevProps, prevState) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_prod.js b/lib/react_prod.js index 48bdc81c..f425a8c5 100644 --- a/lib/react_prod.js +++ b/lib/react_prod.js @@ -37,8 +37,8 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentWillUpdate: function(nextProps, nextState, nextContext) { dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState, prevContext) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); + componentDidUpdate: function(prevProps, prevState) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_with_addons.js b/lib/react_with_addons.js index d00ac10e..332d9db7 100644 --- a/lib/react_with_addons.js +++ b/lib/react_with_addons.js @@ -5986,8 +5986,8 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentWillUpdate: function(nextProps, nextState, nextContext) { dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState, prevContext) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); + componentDidUpdate: function(prevProps, prevState) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); diff --git a/lib/react_with_react_dom_prod.js b/lib/react_with_react_dom_prod.js index 5083821f..c421d153 100644 --- a/lib/react_with_react_dom_prod.js +++ b/lib/react_with_react_dom_prod.js @@ -37,8 +37,8 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati componentWillUpdate: function(nextProps, nextState, nextContext) { dartInteropStatics.handleComponentWillUpdate(this.dartComponent, nextContext); }, - componentDidUpdate: function(prevProps, prevState, prevContext) { - dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal, prevContext); + componentDidUpdate: function(prevProps, prevState) { + dartInteropStatics.handleComponentDidUpdate(this.dartComponent, prevProps.internal); }, componentWillUnmount: function() { dartInteropStatics.handleComponentWillUnmount(this.dartComponent); From bb0bc6cbd60a79f41281e8e99227ea3914cc0464 Mon Sep 17 00:00:00 2001 From: Greg Littlefield Date: Fri, 27 Oct 2017 10:12:50 -0700 Subject: [PATCH 9/9] Rename to handleGetChildContext --- js_src/dart_helpers.js | 2 +- lib/react.js | 2 +- lib/react_client.dart | 4 ++-- lib/react_client/react_interop.dart | 4 ++-- lib/react_prod.js | 2 +- lib/react_with_addons.js | 2 +- lib/react_with_react_dom_prod.js | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/js_src/dart_helpers.js b/js_src/dart_helpers.js index e65669b9..2819cef8 100644 --- a/js_src/dart_helpers.js +++ b/js_src/dart_helpers.js @@ -52,7 +52,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati // Only declare this when `hasChildContext` is true to avoid unnecessarily // creating interop context objects for components that won't use it. config.getChildContext = function() { - return dartInteropStatics.getChildContext(this.dartComponent); + return dartInteropStatics.handleGetChildContext(this.dartComponent); }; } diff --git a/lib/react.js b/lib/react.js index 1651a0da..3f26bc1a 100644 --- a/lib/react.js +++ b/lib/react.js @@ -4371,7 +4371,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati // Only declare this when `hasChildContext` is true to avoid unnecessarily // creating interop context objects for components that won't use it. config.getChildContext = function() { - return dartInteropStatics.getChildContext(this.dartComponent); + return dartInteropStatics.handleGetChildContext(this.dartComponent); }; } diff --git a/lib/react_client.dart b/lib/react_client.dart index 5f2c0f8f..ebe170db 100644 --- a/lib/react_client.dart +++ b/lib/react_client.dart @@ -225,7 +225,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { return component; }); - InteropContextValue getChildContext(Component component) => zone.run(() { + InteropContextValue handleGetChildContext(Component component) => zone.run(() { return _jsifyContext(component.getChildContext()); }); @@ -331,7 +331,7 @@ final ReactDartInteropStatics _dartInteropStatics = (() { return new ReactDartInteropStatics( initComponent: allowInterop(initComponent), - getChildContext: allowInterop(getChildContext), + handleGetChildContext: allowInterop(handleGetChildContext), handleComponentWillMount: allowInterop(handleComponentWillMount), handleComponentDidMount: allowInterop(handleComponentDidMount), handleComponentWillReceiveProps: allowInterop(handleComponentWillReceiveProps), diff --git a/lib/react_client/react_interop.dart b/lib/react_client/react_interop.dart index 0baab30d..10296df5 100644 --- a/lib/react_client/react_interop.dart +++ b/lib/react_client/react_interop.dart @@ -243,7 +243,7 @@ external ReactClassConfig createReactDartComponentClassConfig( ); typedef Component _InitComponent(ReactComponent jsThis, ReactDartComponentInternal internal, InteropContextValue context, ComponentStatics componentStatics); -typedef InteropContextValue _GetChildContext(Component component); +typedef InteropContextValue _HandleGetChildContext(Component component); typedef void _HandleComponentWillMount(Component component); typedef void _HandleComponentDidMount(Component component); typedef void _HandleComponentWillReceiveProps(Component component, ReactDartComponentInternal nextInternal, InteropContextValue nextContext); @@ -260,7 +260,7 @@ typedef dynamic _HandleRender(Component component); class ReactDartInteropStatics { external factory ReactDartInteropStatics({ _InitComponent initComponent, - _GetChildContext getChildContext, + _HandleGetChildContext handleGetChildContext, _HandleComponentWillMount handleComponentWillMount, _HandleComponentDidMount handleComponentDidMount, _HandleComponentWillReceiveProps handleComponentWillReceiveProps, diff --git a/lib/react_prod.js b/lib/react_prod.js index f425a8c5..718358c7 100644 --- a/lib/react_prod.js +++ b/lib/react_prod.js @@ -63,7 +63,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati // Only declare this when `hasChildContext` is true to avoid unnecessarily // creating interop context objects for components that won't use it. config.getChildContext = function() { - return dartInteropStatics.getChildContext(this.dartComponent); + return dartInteropStatics.handleGetChildContext(this.dartComponent); }; } diff --git a/lib/react_with_addons.js b/lib/react_with_addons.js index 332d9db7..46e5cc6f 100644 --- a/lib/react_with_addons.js +++ b/lib/react_with_addons.js @@ -6012,7 +6012,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati // Only declare this when `hasChildContext` is true to avoid unnecessarily // creating interop context objects for components that won't use it. config.getChildContext = function() { - return dartInteropStatics.getChildContext(this.dartComponent); + return dartInteropStatics.handleGetChildContext(this.dartComponent); }; } diff --git a/lib/react_with_react_dom_prod.js b/lib/react_with_react_dom_prod.js index c421d153..b2fbb6bc 100644 --- a/lib/react_with_react_dom_prod.js +++ b/lib/react_with_react_dom_prod.js @@ -63,7 +63,7 @@ function _createReactDartComponentClassConfig(dartInteropStatics, componentStati // Only declare this when `hasChildContext` is true to avoid unnecessarily // creating interop context objects for components that won't use it. config.getChildContext = function() { - return dartInteropStatics.getChildContext(this.dartComponent); + return dartInteropStatics.handleGetChildContext(this.dartComponent); }; }