Skip to content

Commit 47b003a

Browse files
authored
Resolve host configs at build time (facebook#12792)
* Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
1 parent c0fe8d6 commit 47b003a

File tree

76 files changed

+7832
-7817
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+7832
-7817
lines changed

packages/react-art/src/ReactART.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@
66
*/
77

88
import React from 'react';
9-
import ReactFiberReconciler from 'react-reconciler';
9+
import * as ARTRenderer from 'react-reconciler/inline.art';
1010
import Transform from 'art/core/transform';
1111
import Mode from 'art/modes/current';
1212
import FastNoSideEffects from 'art/modes/fast-noSideEffects';
1313

14-
import ReactARTHostConfig from './ReactARTHostConfig';
1514
import {TYPES, childrenAsString} from './ReactARTInternals';
1615

1716
Mode.setCurrent(
@@ -132,10 +131,6 @@ class Text extends React.Component {
132131
}
133132
}
134133

135-
/** ART Renderer */
136-
137-
const ARTRenderer = ReactFiberReconciler(ReactARTHostConfig);
138-
139134
/** API */
140135

141136
export const ClippingRectangle = TYPES.CLIPPING_RECTANGLE;

packages/react-art/src/ReactARTHostConfig.js

Lines changed: 141 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -234,157 +234,167 @@ function applyTextProps(instance, props, prevProps = {}) {
234234
}
235235
}
236236

237-
const ReactARTHostConfig = {
238-
appendInitialChild(parentInstance, child) {
239-
if (typeof child === 'string') {
240-
// Noop for string children of Text (eg <Text>{'foo'}{'bar'}</Text>)
241-
invariant(false, 'Text children should already be flattened.');
242-
return;
243-
}
237+
export * from 'shared/HostConfigWithNoPersistence';
238+
export * from 'shared/HostConfigWithNoHydration';
239+
240+
export function appendInitialChild(parentInstance, child) {
241+
if (typeof child === 'string') {
242+
// Noop for string children of Text (eg <Text>{'foo'}{'bar'}</Text>)
243+
invariant(false, 'Text children should already be flattened.');
244+
return;
245+
}
244246

245-
child.inject(parentInstance);
246-
},
247-
248-
createInstance(type, props, internalInstanceHandle) {
249-
let instance;
250-
251-
switch (type) {
252-
case TYPES.CLIPPING_RECTANGLE:
253-
instance = Mode.ClippingRectangle();
254-
instance._applyProps = applyClippingRectangleProps;
255-
break;
256-
case TYPES.GROUP:
257-
instance = Mode.Group();
258-
instance._applyProps = applyGroupProps;
259-
break;
260-
case TYPES.SHAPE:
261-
instance = Mode.Shape();
262-
instance._applyProps = applyShapeProps;
263-
break;
264-
case TYPES.TEXT:
265-
instance = Mode.Text(
266-
props.children,
267-
props.font,
268-
props.alignment,
269-
props.path,
270-
);
271-
instance._applyProps = applyTextProps;
272-
break;
273-
}
247+
child.inject(parentInstance);
248+
}
274249

275-
invariant(instance, 'ReactART does not support the type "%s"', type);
250+
export function createInstance(type, props, internalInstanceHandle) {
251+
let instance;
252+
253+
switch (type) {
254+
case TYPES.CLIPPING_RECTANGLE:
255+
instance = Mode.ClippingRectangle();
256+
instance._applyProps = applyClippingRectangleProps;
257+
break;
258+
case TYPES.GROUP:
259+
instance = Mode.Group();
260+
instance._applyProps = applyGroupProps;
261+
break;
262+
case TYPES.SHAPE:
263+
instance = Mode.Shape();
264+
instance._applyProps = applyShapeProps;
265+
break;
266+
case TYPES.TEXT:
267+
instance = Mode.Text(
268+
props.children,
269+
props.font,
270+
props.alignment,
271+
props.path,
272+
);
273+
instance._applyProps = applyTextProps;
274+
break;
275+
}
276276

277-
instance._applyProps(instance, props);
277+
invariant(instance, 'ReactART does not support the type "%s"', type);
278278

279-
return instance;
280-
},
279+
instance._applyProps(instance, props);
281280

282-
createTextInstance(text, rootContainerInstance, internalInstanceHandle) {
283-
return text;
284-
},
281+
return instance;
282+
}
285283

286-
finalizeInitialChildren(domElement, type, props) {
287-
return false;
288-
},
284+
export function createTextInstance(
285+
text,
286+
rootContainerInstance,
287+
internalInstanceHandle,
288+
) {
289+
return text;
290+
}
289291

290-
getPublicInstance(instance) {
291-
return instance;
292-
},
292+
export function finalizeInitialChildren(domElement, type, props) {
293+
return false;
294+
}
293295

294-
prepareForCommit() {
295-
// Noop
296-
},
296+
export function getPublicInstance(instance) {
297+
return instance;
298+
}
297299

298-
prepareUpdate(domElement, type, oldProps, newProps) {
299-
return UPDATE_SIGNAL;
300-
},
300+
export function prepareForCommit() {
301+
// Noop
302+
}
301303

302-
resetAfterCommit() {
303-
// Noop
304-
},
304+
export function prepareUpdate(domElement, type, oldProps, newProps) {
305+
return UPDATE_SIGNAL;
306+
}
305307

306-
resetTextContent(domElement) {
307-
// Noop
308-
},
308+
export function resetAfterCommit() {
309+
// Noop
310+
}
309311

310-
shouldDeprioritizeSubtree(type, props) {
311-
return false;
312-
},
312+
export function resetTextContent(domElement) {
313+
// Noop
314+
}
313315

314-
getRootHostContext() {
315-
return emptyObject;
316-
},
316+
export function shouldDeprioritizeSubtree(type, props) {
317+
return false;
318+
}
317319

318-
getChildHostContext() {
319-
return emptyObject;
320-
},
320+
export function getRootHostContext() {
321+
return emptyObject;
322+
}
321323

322-
scheduleDeferredCallback: ReactScheduler.scheduleWork,
324+
export function getChildHostContext() {
325+
return emptyObject;
326+
}
323327

324-
shouldSetTextContent(type, props) {
325-
return (
326-
typeof props.children === 'string' || typeof props.children === 'number'
327-
);
328-
},
329-
330-
now: ReactScheduler.now,
331-
332-
// The ART renderer is secondary to the React DOM renderer.
333-
isPrimaryRenderer: false,
334-
335-
mutation: {
336-
appendChild(parentInstance, child) {
337-
if (child.parentNode === parentInstance) {
338-
child.eject();
339-
}
340-
child.inject(parentInstance);
341-
},
342-
343-
appendChildToContainer(parentInstance, child) {
344-
if (child.parentNode === parentInstance) {
345-
child.eject();
346-
}
347-
child.inject(parentInstance);
348-
},
349-
350-
insertBefore(parentInstance, child, beforeChild) {
351-
invariant(
352-
child !== beforeChild,
353-
'ReactART: Can not insert node before itself',
354-
);
355-
child.injectBefore(beforeChild);
356-
},
328+
export const scheduleDeferredCallback = ReactScheduler.scheduleWork;
329+
export const cancelDeferredCallback = ReactScheduler.cancelScheduledWork;
357330

358-
insertInContainerBefore(parentInstance, child, beforeChild) {
359-
invariant(
360-
child !== beforeChild,
361-
'ReactART: Can not insert node before itself',
362-
);
363-
child.injectBefore(beforeChild);
364-
},
331+
export function shouldSetTextContent(type, props) {
332+
return (
333+
typeof props.children === 'string' || typeof props.children === 'number'
334+
);
335+
}
365336

366-
removeChild(parentInstance, child) {
367-
destroyEventListeners(child);
368-
child.eject();
369-
},
337+
export const now = ReactScheduler.now;
370338

371-
removeChildFromContainer(parentInstance, child) {
372-
destroyEventListeners(child);
373-
child.eject();
374-
},
339+
// The ART renderer is secondary to the React DOM renderer.
340+
export const isPrimaryRenderer = false;
375341

376-
commitTextUpdate(textInstance, oldText, newText) {
377-
// Noop
378-
},
342+
export const supportsMutation = true;
379343

380-
commitMount(instance, type, newProps) {
381-
// Noop
382-
},
344+
export function appendChild(parentInstance, child) {
345+
if (child.parentNode === parentInstance) {
346+
child.eject();
347+
}
348+
child.inject(parentInstance);
349+
}
383350

384-
commitUpdate(instance, updatePayload, type, oldProps, newProps) {
385-
instance._applyProps(instance, newProps, oldProps);
386-
},
387-
},
388-
};
351+
export function appendChildToContainer(parentInstance, child) {
352+
if (child.parentNode === parentInstance) {
353+
child.eject();
354+
}
355+
child.inject(parentInstance);
356+
}
389357

390-
export default ReactARTHostConfig;
358+
export function insertBefore(parentInstance, child, beforeChild) {
359+
invariant(
360+
child !== beforeChild,
361+
'ReactART: Can not insert node before itself',
362+
);
363+
child.injectBefore(beforeChild);
364+
}
365+
366+
export function insertInContainerBefore(parentInstance, child, beforeChild) {
367+
invariant(
368+
child !== beforeChild,
369+
'ReactART: Can not insert node before itself',
370+
);
371+
child.injectBefore(beforeChild);
372+
}
373+
374+
export function removeChild(parentInstance, child) {
375+
destroyEventListeners(child);
376+
child.eject();
377+
}
378+
379+
export function removeChildFromContainer(parentInstance, child) {
380+
destroyEventListeners(child);
381+
child.eject();
382+
}
383+
384+
export function commitTextUpdate(textInstance, oldText, newText) {
385+
// Noop
386+
}
387+
388+
export function commitMount(instance, type, newProps) {
389+
// Noop
390+
}
391+
392+
export function commitUpdate(
393+
instance,
394+
updatePayload,
395+
type,
396+
oldProps,
397+
newProps,
398+
) {
399+
instance._applyProps(instance, newProps, oldProps);
400+
}

0 commit comments

Comments
 (0)