- 37개 파일 IP → zioinfo.co.kr 치환 (소스/매뉴얼/설정/하네스) - Manager DrConsole/NetworkConsole/CsapConsole 빌드 + /var/www/manager/ 배포 - 테스트: Manager HTTP 200, ITSM 신규 API 7개 전체 200 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
455 lines
12 KiB
Plaintext
455 lines
12 KiB
Plaintext
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
import type {EventTypeShape} from '../../CodegenSchema';
|
|
import type {
|
|
ComponentShape,
|
|
EventTypeAnnotation,
|
|
NamedShape,
|
|
ObjectTypeAnnotation,
|
|
SchemaType,
|
|
} from '../../CodegenSchema';
|
|
|
|
const {indent} = require('../Utils');
|
|
const {IncludeTemplate, generateEventStructName} = require('./CppHelpers');
|
|
|
|
// File path -> contents
|
|
type FilesOutput = Map<string, string>;
|
|
|
|
type ComponentCollection = $ReadOnly<{
|
|
[component: string]: ComponentShape,
|
|
...
|
|
}>;
|
|
|
|
const FileTemplate = ({
|
|
events,
|
|
extraIncludes,
|
|
headerPrefix,
|
|
}: {
|
|
events: string,
|
|
extraIncludes: Set<string>,
|
|
headerPrefix: string,
|
|
}) => `
|
|
/**
|
|
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
*
|
|
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
* once the code is regenerated.
|
|
*
|
|
* ${'@'}generated by codegen project: GenerateEventEmitterCpp.js
|
|
*/
|
|
|
|
${IncludeTemplate({headerPrefix, file: 'EventEmitters.h'})}
|
|
${[...extraIncludes].join('\n')}
|
|
|
|
namespace facebook::react {
|
|
${events}
|
|
} // namespace facebook::react
|
|
`;
|
|
|
|
const ComponentTemplate = ({
|
|
className,
|
|
eventName,
|
|
structName,
|
|
dispatchEventName,
|
|
implementation,
|
|
}: {
|
|
className: string,
|
|
eventName: string,
|
|
structName: string,
|
|
dispatchEventName: string,
|
|
implementation: string,
|
|
}) => {
|
|
const capture = implementation.includes('$event')
|
|
? '$event=std::move($event)'
|
|
: '';
|
|
return `
|
|
void ${className}EventEmitter::${eventName}(${structName} $event) const {
|
|
dispatchEvent("${dispatchEventName}", [${capture}](jsi::Runtime &runtime) {
|
|
${implementation}
|
|
});
|
|
}
|
|
`;
|
|
};
|
|
|
|
const BasicComponentTemplate = ({
|
|
className,
|
|
eventName,
|
|
dispatchEventName,
|
|
}: {
|
|
className: string,
|
|
eventName: string,
|
|
dispatchEventName: string,
|
|
}) =>
|
|
`
|
|
void ${className}EventEmitter::${eventName}() const {
|
|
dispatchEvent("${dispatchEventName}");
|
|
}
|
|
`.trim();
|
|
|
|
function generateSetter(
|
|
variableName: string,
|
|
propertyName: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
usingEvent: boolean,
|
|
valueMapper: string => string = value => value,
|
|
) {
|
|
const eventChain = usingEvent
|
|
? `$event.${[...propertyParts, propertyName].join('.')}`
|
|
: [propertyParts, propertyName].join('.');
|
|
return `${variableName}.setProperty(runtime, "${propertyName}", ${valueMapper(
|
|
eventChain,
|
|
)});`;
|
|
}
|
|
|
|
function generateObjectSetter(
|
|
variableName: string,
|
|
propertyName: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
typeAnnotation: ObjectTypeAnnotation<EventTypeAnnotation>,
|
|
extraIncludes: Set<string>,
|
|
usingEvent: boolean,
|
|
) {
|
|
return `
|
|
{
|
|
auto ${propertyName} = jsi::Object(runtime);
|
|
${indent(
|
|
generateSetters(
|
|
propertyName,
|
|
typeAnnotation.properties,
|
|
propertyParts.concat([propertyName]),
|
|
extraIncludes,
|
|
usingEvent,
|
|
),
|
|
2,
|
|
)}
|
|
${variableName}.setProperty(runtime, "${propertyName}", ${propertyName});
|
|
}
|
|
`.trim();
|
|
}
|
|
|
|
function setValueAtIndex(
|
|
propertyName: string,
|
|
indexVariable: string,
|
|
loopLocalVariable: string,
|
|
mappingFunction: string => string = value => value,
|
|
) {
|
|
return `${propertyName}.setValueAtIndex(runtime, ${indexVariable}++, ${mappingFunction(
|
|
loopLocalVariable,
|
|
)});`;
|
|
}
|
|
|
|
function generateArraySetter(
|
|
variableName: string,
|
|
propertyName: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
elementType: EventTypeAnnotation,
|
|
extraIncludes: Set<string>,
|
|
usingEvent: boolean,
|
|
): string {
|
|
const eventChain = usingEvent
|
|
? `$event.${[...propertyParts, propertyName].join('.')}`
|
|
: [propertyParts, propertyName].join('.');
|
|
const indexVar = `${propertyName}Index`;
|
|
const innerLoopVar = `${propertyName}Value`;
|
|
return `
|
|
auto ${propertyName} = jsi::Array(runtime, ${eventChain}.size());
|
|
size_t ${indexVar} = 0;
|
|
for (auto ${innerLoopVar} : ${eventChain}) {
|
|
${handleArrayElementType(
|
|
elementType,
|
|
propertyName,
|
|
indexVar,
|
|
innerLoopVar,
|
|
propertyParts,
|
|
extraIncludes,
|
|
usingEvent,
|
|
)}
|
|
}
|
|
${variableName}.setProperty(runtime, "${propertyName}", ${propertyName});
|
|
`;
|
|
}
|
|
|
|
function handleArrayElementType(
|
|
elementType: EventTypeAnnotation,
|
|
propertyName: string,
|
|
indexVariable: string,
|
|
loopLocalVariable: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
extraIncludes: Set<string>,
|
|
usingEvent: boolean,
|
|
): string {
|
|
switch (elementType.type) {
|
|
case 'BooleanTypeAnnotation':
|
|
return setValueAtIndex(
|
|
propertyName,
|
|
indexVariable,
|
|
loopLocalVariable,
|
|
val => `(bool)${val}`,
|
|
);
|
|
case 'StringTypeAnnotation':
|
|
case 'Int32TypeAnnotation':
|
|
case 'DoubleTypeAnnotation':
|
|
case 'FloatTypeAnnotation':
|
|
return setValueAtIndex(propertyName, indexVariable, loopLocalVariable);
|
|
case 'MixedTypeAnnotation':
|
|
return setValueAtIndex(
|
|
propertyName,
|
|
indexVariable,
|
|
loopLocalVariable,
|
|
val => `jsi::valueFromDynamic(runtime, ${val})`,
|
|
);
|
|
case 'StringEnumTypeAnnotation':
|
|
return setValueAtIndex(
|
|
propertyName,
|
|
indexVariable,
|
|
loopLocalVariable,
|
|
val => `toString(${val})`,
|
|
);
|
|
case 'ObjectTypeAnnotation':
|
|
return convertObjectTypeArray(
|
|
propertyName,
|
|
indexVariable,
|
|
loopLocalVariable,
|
|
propertyParts,
|
|
elementType,
|
|
extraIncludes,
|
|
);
|
|
case 'ArrayTypeAnnotation':
|
|
return convertArrayTypeArray(
|
|
propertyName,
|
|
indexVariable,
|
|
loopLocalVariable,
|
|
propertyParts,
|
|
elementType,
|
|
extraIncludes,
|
|
usingEvent,
|
|
);
|
|
default:
|
|
throw new Error(
|
|
`Received invalid elementType for array ${elementType.type}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function convertObjectTypeArray(
|
|
propertyName: string,
|
|
indexVariable: string,
|
|
loopLocalVariable: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
objectTypeAnnotation: ObjectTypeAnnotation<EventTypeAnnotation>,
|
|
extraIncludes: Set<string>,
|
|
): string {
|
|
return `auto ${propertyName}Object = jsi::Object(runtime);
|
|
${generateSetters(
|
|
`${propertyName}Object`,
|
|
objectTypeAnnotation.properties,
|
|
[].concat([loopLocalVariable]),
|
|
extraIncludes,
|
|
false,
|
|
)}
|
|
${setValueAtIndex(propertyName, indexVariable, `${propertyName}Object`)}`;
|
|
}
|
|
|
|
function convertArrayTypeArray(
|
|
propertyName: string,
|
|
indexVariable: string,
|
|
loopLocalVariable: string,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
eventTypeAnnotation: EventTypeAnnotation,
|
|
extraIncludes: Set<string>,
|
|
usingEvent: boolean,
|
|
): string {
|
|
if (eventTypeAnnotation.type !== 'ArrayTypeAnnotation') {
|
|
throw new Error(
|
|
`Inconsistent eventTypeAnnotation received. Expected type = 'ArrayTypeAnnotation'; received = ${eventTypeAnnotation.type}`,
|
|
);
|
|
}
|
|
return `auto ${propertyName}Array = jsi::Array(runtime, ${loopLocalVariable}.size());
|
|
size_t ${indexVariable}Internal = 0;
|
|
for (auto ${loopLocalVariable}Internal : ${loopLocalVariable}) {
|
|
${handleArrayElementType(
|
|
eventTypeAnnotation.elementType,
|
|
`${propertyName}Array`,
|
|
`${indexVariable}Internal`,
|
|
`${loopLocalVariable}Internal`,
|
|
propertyParts,
|
|
extraIncludes,
|
|
usingEvent,
|
|
)}
|
|
}
|
|
${setValueAtIndex(propertyName, indexVariable, `${propertyName}Array`)}`;
|
|
}
|
|
|
|
function generateSetters(
|
|
parentPropertyName: string,
|
|
properties: $ReadOnlyArray<NamedShape<EventTypeAnnotation>>,
|
|
propertyParts: $ReadOnlyArray<string>,
|
|
extraIncludes: Set<string>,
|
|
usingEvent: boolean = true,
|
|
): string {
|
|
const propSetters = properties
|
|
.map(eventProperty => {
|
|
const {typeAnnotation} = eventProperty;
|
|
switch (typeAnnotation.type) {
|
|
case 'BooleanTypeAnnotation':
|
|
case 'StringTypeAnnotation':
|
|
case 'Int32TypeAnnotation':
|
|
case 'DoubleTypeAnnotation':
|
|
case 'FloatTypeAnnotation':
|
|
return generateSetter(
|
|
parentPropertyName,
|
|
eventProperty.name,
|
|
propertyParts,
|
|
usingEvent,
|
|
);
|
|
case 'MixedTypeAnnotation':
|
|
extraIncludes.add('#include <jsi/JSIDynamic.h>');
|
|
return generateSetter(
|
|
parentPropertyName,
|
|
eventProperty.name,
|
|
propertyParts,
|
|
usingEvent,
|
|
prop => `jsi::valueFromDynamic(runtime, ${prop})`,
|
|
);
|
|
case 'StringEnumTypeAnnotation':
|
|
return generateSetter(
|
|
parentPropertyName,
|
|
eventProperty.name,
|
|
propertyParts,
|
|
usingEvent,
|
|
prop => `toString(${prop})`,
|
|
);
|
|
case 'ObjectTypeAnnotation':
|
|
return generateObjectSetter(
|
|
parentPropertyName,
|
|
eventProperty.name,
|
|
propertyParts,
|
|
typeAnnotation,
|
|
extraIncludes,
|
|
usingEvent,
|
|
);
|
|
case 'ArrayTypeAnnotation':
|
|
return generateArraySetter(
|
|
parentPropertyName,
|
|
eventProperty.name,
|
|
propertyParts,
|
|
typeAnnotation.elementType,
|
|
extraIncludes,
|
|
usingEvent,
|
|
);
|
|
default:
|
|
(typeAnnotation.type: empty);
|
|
throw new Error(
|
|
`Received invalid event property type ${typeAnnotation.type}`,
|
|
);
|
|
}
|
|
})
|
|
.join('\n');
|
|
|
|
return propSetters;
|
|
}
|
|
|
|
function generateEvent(
|
|
componentName: string,
|
|
event: EventTypeShape,
|
|
extraIncludes: Set<string>,
|
|
): string {
|
|
// 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.
|
|
// In order to migrate to this new system we have to support the current
|
|
// naming scheme. We should delete this once we are able to control this name
|
|
// throughout the system.
|
|
const dispatchEventName =
|
|
event.paperTopLevelNameDeprecated != null
|
|
? event.paperTopLevelNameDeprecated
|
|
: `${event.name[2].toLowerCase()}${event.name.slice(3)}`;
|
|
|
|
if (event.typeAnnotation.argument) {
|
|
const implementation = `
|
|
auto $payload = jsi::Object(runtime);
|
|
${generateSetters(
|
|
'$payload',
|
|
event.typeAnnotation.argument.properties,
|
|
[],
|
|
extraIncludes,
|
|
)}
|
|
return $payload;
|
|
`.trim();
|
|
|
|
if (!event.name.startsWith('on')) {
|
|
throw new Error('Expected the event name to start with `on`');
|
|
}
|
|
|
|
return ComponentTemplate({
|
|
className: componentName,
|
|
eventName: event.name,
|
|
dispatchEventName,
|
|
structName: generateEventStructName([event.name]),
|
|
implementation,
|
|
});
|
|
}
|
|
|
|
return BasicComponentTemplate({
|
|
className: componentName,
|
|
eventName: event.name,
|
|
dispatchEventName,
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
generate(
|
|
libraryName: string,
|
|
schema: SchemaType,
|
|
packageName?: string,
|
|
assumeNonnull: boolean = false,
|
|
headerPrefix?: string,
|
|
): FilesOutput {
|
|
const moduleComponents: ComponentCollection = Object.keys(schema.modules)
|
|
.map(moduleName => {
|
|
const module = schema.modules[moduleName];
|
|
if (module.type !== 'Component') {
|
|
return;
|
|
}
|
|
|
|
const {components} = module;
|
|
// No components in this module
|
|
if (components == null) {
|
|
return null;
|
|
}
|
|
|
|
return components;
|
|
})
|
|
.filter(Boolean)
|
|
.reduce((acc, components) => Object.assign(acc, components), {});
|
|
|
|
const extraIncludes = new Set<string>();
|
|
const componentEmitters = Object.keys(moduleComponents)
|
|
.map(componentName => {
|
|
const component = moduleComponents[componentName];
|
|
return component.events
|
|
.map(event => generateEvent(componentName, event, extraIncludes))
|
|
.join('\n');
|
|
})
|
|
.join('\n');
|
|
|
|
const fileName = 'EventEmitters.cpp';
|
|
const replacedTemplate = FileTemplate({
|
|
events: componentEmitters,
|
|
extraIncludes,
|
|
headerPrefix: headerPrefix ?? '',
|
|
});
|
|
|
|
return new Map([[fileName, replacedTemplate]]);
|
|
},
|
|
};
|