Generate events with no arguments

Summary:
This diff allows generating native events without any arguments with an event like:

```
{
  name: 'onEnd',
  optional: true,
  bubblingType: 'bubble',
  typeAnnotation: {
    type: 'EventTypeAnnotation',
    // note: no argument key
  },
},
```

See the snapshot updates in the diff for the native code that will be generated �

Reviewed By: shergin

Differential Revision: D15403791

fbshipit-source-id: 925a49bb477eebb234e181df681f0d6b1d4e8cf1
This commit is contained in:
Rick Hanlon
2019-05-22 05:36:20 -07:00
committed by Facebook Github Bot
parent d7a5e3e215
commit de33b8a237
7 changed files with 66 additions and 26 deletions
+1 -1
View File
@@ -83,7 +83,7 @@ export type EventTypeShape = $ReadOnly<{|
optional: boolean,
typeAnnotation: $ReadOnly<{|
type: 'EventTypeAnnotation',
argument: $ReadOnly<{|
argument?: $ReadOnly<{|
type: 'ObjectTypeAnnotation',
properties: $ReadOnlyArray<ObjectPropertyType>,
|}>,
@@ -55,6 +55,12 @@ void ::_CLASSNAME_::EventEmitter::::_EVENT_NAME_::(::_STRUCT_NAME_:: event) cons
}
`.trim();
const basicComponentTemplate = `
void ::_CLASSNAME_::EventEmitter::::_EVENT_NAME_::() const {
dispatchEvent("::_DISPATCH_EVENT_NAME_::");
}
`.trim();
function generateSetter(variableName, propertyName, propertyParts) {
const trailingPeriod = propertyParts.length === 0 ? '' : '.';
const eventChain = `event.${propertyParts.join(
@@ -106,16 +112,6 @@ function generateSetters(
}
function generateEvent(componentName: string, event): string {
const implementation = `
auto payload = jsi::Object(runtime);
${generateSetters('payload', event.typeAnnotation.argument.properties, [])}
return payload;
`.trim();
if (!event.name.startsWith('on')) {
throw new Error('Expected the event name to start with `on`');
}
// This is a gross hack necessary because native code is sending
// events named things like topChange to JS which is then converted back to
// call the onChange prop. We should be consistent throughout the system.
@@ -126,15 +122,32 @@ function generateEvent(componentName: string, event): string {
3,
)}`;
return componentTemplate
if (event.typeAnnotation.argument) {
const implementation = `
auto payload = jsi::Object(runtime);
${generateSetters('payload', event.typeAnnotation.argument.properties, [])}
return payload;
`.trim();
if (!event.name.startsWith('on')) {
throw new Error('Expected the event name to start with `on`');
}
return componentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace(/::_EVENT_NAME_::/g, event.name)
.replace(/::_DISPATCH_EVENT_NAME_::/g, dispatchEventName)
.replace(
'::_STRUCT_NAME_::',
generateStructName(componentName, [event.name]),
)
.replace('::_IMPLEMENTATION_::', implementation);
}
return basicComponentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace(/::_EVENT_NAME_::/g, event.name)
.replace(/::_DISPATCH_EVENT_NAME_::/g, dispatchEventName)
.replace(
'::_STRUCT_NAME_::',
generateStructName(componentName, [event.name]),
)
.replace('::_IMPLEMENTATION_::', implementation);
.replace(/::_DISPATCH_EVENT_NAME_::/g, dispatchEventName);
}
module.exports = {
@@ -146,21 +146,27 @@ function generateStructs(componentName: string, component): string {
const structs: StructsMap = new Map();
component.events.forEach(event => {
generateStruct(
structs,
componentName,
[event.name],
event.typeAnnotation.argument.properties,
);
if (event.typeAnnotation.argument) {
generateStruct(
structs,
componentName,
[event.name],
event.typeAnnotation.argument.properties,
);
}
});
return Array.from(structs.values()).join('\n\n');
}
function generateEvent(componentName: string, event: EventTypeShape): string {
const structName = generateStructName(componentName, [event.name]);
if (event.typeAnnotation.argument) {
const structName = generateStructName(componentName, [event.name]);
return `void ${event.name}(${structName} value) const;`;
return `void ${event.name}(${structName} value) const;`;
}
return `void ${event.name}() const;`;
}
function generateEvents(componentName: string, component): string {
return component.events
@@ -560,6 +560,14 @@ const EVENT_PROPS: SchemaType = {
},
},
},
{
name: 'onEnd',
optional: true,
bubblingType: 'bubble',
typeAnnotation: {
type: 'EventTypeAnnotation',
},
},
],
props: [
{
@@ -165,6 +165,9 @@ void EventsNativeComponentEventEmitter::onEventDirect(EventsNativeComponentOnEve
return payload;
});
}
void EventsNativeComponentEventEmitter::onEnd() const {
dispatchEvent(\\"end\\");
}
} // namespace react
} // namespace facebook
@@ -173,6 +173,8 @@ class EventsNativeComponentEventEmitter : public ViewEventEmitter {
void onChange(EventsNativeComponentOnChangeStruct value) const;
void onEventDirect(EventsNativeComponentOnEventDirectStruct value) const;
void onEnd() const;
};
} // namespace react
@@ -285,6 +285,13 @@ const EventsNativeComponentViewConfig = {
bubbled: 'onChange',
},
},
topEnd: {
phasedRegistrationNames: {
captured: 'onEndCapture',
bubbled: 'onEnd',
},
},
},
directEventTypes: {
@@ -300,6 +307,7 @@ const EventsNativeComponentViewConfig = {
disabled: true,
onChange: true,
onEventDirect: true,
onEnd: true,
},
};