Socket
Socket
Sign inDemoInstall

react-native-tscodegen

Package Overview
Dependencies
Maintainers
4
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-native-tscodegen - npm Package Compare versions

Comparing version 0.68.5 to 0.71.0

lib/rncodegen/src/generators/__test_fixtures__/fixtures.js

16

CHANGELOG.json

@@ -5,3 +5,17 @@ {

{
"date": "Wed, 08 Jun 2022 20:03:27 GMT",
"date": "Wed, 30 Nov 2022 15:29:30 GMT",
"tag": "react-native-tscodegen_v0.71.0",
"version": "0.71.0",
"comments": {
"minor": [
{
"comment": "Catch up react-native-codegen 0.72",
"author": "53799235+ZihanChen-MSFT@users.noreply.github.com",
"commit": "48000f95ea4968cd6d080bbb521f40ad5e4099a3"
}
]
}
},
{
"date": "Wed, 08 Jun 2022 20:03:29 GMT",
"tag": "react-native-tscodegen_v0.68.5",

@@ -8,0 +22,0 @@ "version": "0.68.5",

10

CHANGELOG.md
# Change Log - react-native-tscodegen
This log was last generated on Wed, 08 Jun 2022 20:03:27 GMT and should not be manually modified.
This log was last generated on Wed, 30 Nov 2022 15:29:30 GMT and should not be manually modified.
## 0.71.0
Wed, 30 Nov 2022 15:29:30 GMT
### Minor changes
- Catch up react-native-codegen 0.72 (53799235+ZihanChen-MSFT@users.noreply.github.com)
## 0.68.5
Wed, 08 Jun 2022 20:03:27 GMT
Wed, 08 Jun 2022 20:03:29 GMT

@@ -8,0 +14,0 @@ ### Patches

export declare type PlatformType = 'iOS' | 'android';
export declare type SchemaType = Readonly<{
modules: Readonly<{
export interface SchemaType {
readonly modules: {
[hasteModuleName: string]: ComponentSchema | NativeModuleSchema;
}>;
}>;
export declare type DoubleTypeAnnotation = Readonly<{
type: 'DoubleTypeAnnotation';
}>;
export declare type FloatTypeAnnotation = Readonly<{
type: 'FloatTypeAnnotation';
}>;
export declare type BooleanTypeAnnotation = Readonly<{
type: 'BooleanTypeAnnotation';
}>;
export declare type Int32TypeAnnotation = Readonly<{
type: 'Int32TypeAnnotation';
}>;
export declare type StringTypeAnnotation = Readonly<{
type: 'StringTypeAnnotation';
}>;
export declare type StringEnumTypeAnnotation = Readonly<{
type: 'StringEnumTypeAnnotation';
options: ReadonlyArray<string>;
}>;
export declare type VoidTypeAnnotation = Readonly<{
type: 'VoidTypeAnnotation';
}>;
export declare type ObjectTypeAnnotation<T> = Readonly<{
type: 'ObjectTypeAnnotation';
properties: ReadonlyArray<NamedShape<T>>;
}>;
export declare type FunctionTypeAnnotation<P, R> = Readonly<{
type: 'FunctionTypeAnnotation';
params: ReadonlyArray<NamedShape<P>>;
returnTypeAnnotation: R;
}>;
export declare type NamedShape<T> = Readonly<{
name: string;
optional: boolean;
typeAnnotation: T;
}>;
export declare type ComponentSchema = Readonly<{
type: 'Component';
components: Readonly<{
};
}
export interface DoubleTypeAnnotation {
readonly type: 'DoubleTypeAnnotation';
}
export interface FloatTypeAnnotation {
readonly type: 'FloatTypeAnnotation';
}
export interface BooleanTypeAnnotation {
readonly type: 'BooleanTypeAnnotation';
}
export interface Int32TypeAnnotation {
readonly type: 'Int32TypeAnnotation';
}
export interface StringTypeAnnotation {
readonly type: 'StringTypeAnnotation';
}
export interface StringEnumTypeAnnotation {
readonly type: 'StringEnumTypeAnnotation';
readonly options: readonly string[];
}
export interface VoidTypeAnnotation {
readonly type: 'VoidTypeAnnotation';
}
export interface ObjectTypeAnnotation<T> {
readonly type: 'ObjectTypeAnnotation';
readonly properties: readonly NamedShape<T>[];
}
export interface FunctionTypeAnnotation<P, R> {
readonly type: 'FunctionTypeAnnotation';
readonly params: readonly NamedShape<P>[];
readonly returnTypeAnnotation: R;
}
export interface NamedShape<T> {
readonly name: string;
readonly optional: boolean;
readonly typeAnnotation: T;
}
export interface ComponentSchema {
readonly type: 'Component';
readonly components: {
[componentName: string]: ComponentShape;
}>;
}>;
export declare type ComponentShape = Readonly<OptionsShape & {
extendsProps: ReadonlyArray<ExtendsPropsShape>;
events: ReadonlyArray<EventTypeShape>;
props: ReadonlyArray<NamedShape<PropTypeAnnotation>>;
commands: ReadonlyArray<NamedShape<CommandTypeAnnotation>>;
}>;
export declare type OptionsShape = Readonly<{
interfaceOnly?: boolean;
paperComponentName?: string;
excludedPlatforms?: ReadonlyArray<PlatformType>;
paperComponentNameDeprecated?: string;
}>;
export declare type ExtendsPropsShape = Readonly<{
type: 'ReactNativeBuiltInType';
knownTypeName: 'ReactNativeCoreViewProps';
}>;
export declare type EventTypeShape = Readonly<{
name: string;
bubblingType: 'direct' | 'bubble';
optional: boolean;
paperTopLevelNameDeprecated?: string;
typeAnnotation: Readonly<{
type: 'EventTypeAnnotation';
argument?: ObjectTypeAnnotation<EventTypeAnnotation>;
}>;
}>;
export interface ObjectTypeAnnotation_EventTypeAnnotation extends ObjectTypeAnnotation<EventTypeAnnotation> {
};
}
export declare type EventTypeAnnotation = BooleanTypeAnnotation | StringTypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | Int32TypeAnnotation | StringEnumTypeAnnotation | ObjectTypeAnnotation_EventTypeAnnotation;
export interface ObjectTypeAnnotation_PropTypeAnnotation extends ObjectTypeAnnotation<PropTypeAnnotation> {
export interface ComponentShape extends OptionsShape {
readonly extendsProps: readonly ExtendsPropsShape[];
readonly events: readonly EventTypeShape[];
readonly props: readonly NamedShape<PropTypeAnnotation>[];
readonly commands: readonly NamedShape<CommandTypeAnnotation>[];
}
export declare type PropTypeAnnotation = Readonly<{
type: 'BooleanTypeAnnotation';
default: boolean | null;
}> | Readonly<{
type: 'StringTypeAnnotation';
default: string | null;
}> | Readonly<{
type: 'DoubleTypeAnnotation';
default: number;
}> | Readonly<{
type: 'FloatTypeAnnotation';
default: number | null;
}> | Readonly<{
type: 'Int32TypeAnnotation';
default: number;
}> | Readonly<{
type: 'StringEnumTypeAnnotation';
default: string;
options: ReadonlyArray<string>;
}> | Readonly<{
type: 'Int32EnumTypeAnnotation';
default: number;
options: ReadonlyArray<number>;
}> | ReservedPropTypeAnnotation | ObjectTypeAnnotation_PropTypeAnnotation | Readonly<{
type: 'ArrayTypeAnnotation';
elementType: BooleanTypeAnnotation | StringTypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | Int32TypeAnnotation | Readonly<{
type: 'StringEnumTypeAnnotation';
default: string;
options: ReadonlyArray<string>;
}> | ObjectTypeAnnotation<PropTypeAnnotation> | ReservedPropTypeAnnotation | Readonly<{
type: 'ArrayTypeAnnotation';
elementType: ObjectTypeAnnotation<PropTypeAnnotation>;
}>;
}>;
export declare type ReservedPropTypeAnnotation = Readonly<{
type: 'ReservedPropTypeAnnotation';
name: 'ColorPrimitive' | 'ImageSourcePrimitive' | 'PointPrimitive' | 'EdgeInsetsPrimitive';
}>;
export interface OptionsShape {
readonly interfaceOnly?: boolean;
readonly paperComponentName?: string;
readonly excludedPlatforms?: readonly PlatformType[];
readonly paperComponentNameDeprecated?: string;
}
export interface ExtendsPropsShape {
readonly type: 'ReactNativeBuiltInType';
readonly knownTypeName: 'ReactNativeCoreViewProps';
}
export interface EventTypeShape {
readonly name: string;
readonly bubblingType: 'direct' | 'bubble';
readonly optional: boolean;
readonly paperTopLevelNameDeprecated?: string;
readonly typeAnnotation: {
readonly type: 'EventTypeAnnotation';
readonly argument?: ObjectTypeAnnotation<EventTypeAnnotation>;
};
}
export declare type EventTypeAnnotation = BooleanTypeAnnotation | StringTypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | Int32TypeAnnotation | StringEnumTypeAnnotation | ObjectTypeAnnotation<EventTypeAnnotation>;
export declare type PropTypeAnnotation = {
readonly type: 'BooleanTypeAnnotation';
readonly default: boolean | null;
} | {
readonly type: 'StringTypeAnnotation';
readonly default: string | null;
} | {
readonly type: 'DoubleTypeAnnotation';
readonly default: number;
} | {
readonly type: 'FloatTypeAnnotation';
readonly default: number | null;
} | {
readonly type: 'Int32TypeAnnotation';
readonly default: number;
} | {
readonly type: 'StringEnumTypeAnnotation';
readonly default: string;
readonly options: readonly string[];
} | {
readonly type: 'Int32EnumTypeAnnotation';
readonly default: number;
readonly options: readonly number[];
} | ReservedPropTypeAnnotation | ObjectTypeAnnotation<PropTypeAnnotation> | {
readonly type: 'ArrayTypeAnnotation';
readonly elementType: BooleanTypeAnnotation | StringTypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | Int32TypeAnnotation | {
readonly type: 'StringEnumTypeAnnotation';
readonly default: string;
readonly options: readonly string[];
} | ObjectTypeAnnotation<PropTypeAnnotation> | ReservedPropTypeAnnotation | {
readonly type: 'ArrayTypeAnnotation';
readonly elementType: ObjectTypeAnnotation<PropTypeAnnotation>;
};
};
export interface ReservedPropTypeAnnotation {
readonly type: 'ReservedPropTypeAnnotation';
readonly name: 'ColorPrimitive' | 'ImageSourcePrimitive' | 'PointPrimitive' | 'EdgeInsetsPrimitive' | 'ImageRequestPrimitive';
}
export declare type CommandTypeAnnotation = FunctionTypeAnnotation<CommandParamTypeAnnotation, VoidTypeAnnotation>;
export declare type CommandParamTypeAnnotation = ReservedTypeAnnotation | BooleanTypeAnnotation | Int32TypeAnnotation | DoubleTypeAnnotation | FloatTypeAnnotation | StringTypeAnnotation;
export declare type ReservedTypeAnnotation = Readonly<{
type: 'ReservedTypeAnnotation';
name: 'RootTag';
}>;
export interface ReservedTypeAnnotation {
readonly type: 'ReservedTypeAnnotation';
readonly name: 'RootTag';
}
export declare type Nullable<T extends NativeModuleTypeAnnotation> = NullableTypeAnnotation<T> | T;
export declare type NullableTypeAnnotation<T extends NativeModuleTypeAnnotation> = Readonly<{
type: 'NullableTypeAnnotation';
typeAnnotation: T;
}>;
export declare type NativeModuleSchema = Readonly<{
type: 'NativeModule';
aliases: NativeModuleAliasMap;
spec: NativeModuleSpec;
moduleNames: ReadonlyArray<string>;
excludedPlatforms?: ReadonlyArray<PlatformType>;
}>;
export declare type NativeModuleSpec = Readonly<{
properties: ReadonlyArray<NativeModulePropertyShape>;
}>;
export interface NullableTypeAnnotation<T extends NativeModuleTypeAnnotation> {
readonly type: 'NullableTypeAnnotation';
readonly typeAnnotation: T;
}
export interface NativeModuleSchema {
readonly type: 'NativeModule';
readonly aliases: NativeModuleAliasMap;
readonly spec: NativeModuleSpec;
readonly moduleNames: readonly string[];
readonly excludedPlatforms?: readonly PlatformType[];
}
export interface NativeModuleSpec {
readonly properties: readonly NativeModulePropertyShape[];
}
export declare type NativeModulePropertyShape = NamedShape<Nullable<NativeModuleFunctionTypeAnnotation>>;
export declare type NativeModuleAliasMap = Readonly<{
[aliasName: string]: NativeModuleObjectTypeAnnotation;
}>;
export interface NativeModuleFunctionTypeAnnotation extends FunctionTypeAnnotation<Nullable<NativeModuleParamTypeAnnotation>, Nullable<NativeModuleReturnTypeAnnotation>> {
export interface NativeModuleAliasMap {
readonly [aliasName: string]: NativeModuleObjectTypeAnnotation;
}
export interface NativeModuleObjectTypeAnnotation extends ObjectTypeAnnotation<Nullable<NativeModuleBaseTypeAnnotation>> {
export declare type NativeModuleFunctionTypeAnnotation = FunctionTypeAnnotation<Nullable<NativeModuleParamTypeAnnotation>, Nullable<NativeModuleReturnTypeAnnotation>>;
export declare type NativeModuleObjectTypeAnnotation = ObjectTypeAnnotation<Nullable<NativeModuleBaseTypeAnnotation>>;
export interface NativeModuleArrayTypeAnnotation<T extends Nullable<NativeModuleBaseTypeAnnotation>> {
readonly type: 'ArrayTypeAnnotation';
readonly elementType?: T;
}
export declare type NativeModuleArrayTypeAnnotation<T extends Nullable<NativeModuleBaseTypeAnnotation>> = Readonly<{
type: 'ArrayTypeAnnotation';
elementType?: T;
}>;
export declare type NativeModuleStringTypeAnnotation = Readonly<{
type: 'StringTypeAnnotation';
}>;
export declare type NativeModuleNumberTypeAnnotation = Readonly<{
type: 'NumberTypeAnnotation';
}>;
export declare type NativeModuleInt32TypeAnnotation = Readonly<{
type: 'Int32TypeAnnotation';
}>;
export declare type NativeModuleDoubleTypeAnnotation = Readonly<{
type: 'DoubleTypeAnnotation';
}>;
export declare type NativeModuleFloatTypeAnnotation = Readonly<{
type: 'FloatTypeAnnotation';
}>;
export declare type NativeModuleBooleanTypeAnnotation = Readonly<{
type: 'BooleanTypeAnnotation';
}>;
export declare type NativeModuleGenericObjectTypeAnnotation = Readonly<{
type: 'GenericObjectTypeAnnotation';
}>;
export declare type NativeModuleTypeAliasTypeAnnotation = Readonly<{
type: 'TypeAliasTypeAnnotation';
name: string;
}>;
export declare type NativeModulePromiseTypeAnnotation = Readonly<{
type: 'PromiseTypeAnnotation';
}>;
export interface NativeModuleArrayTypeAnnotation_Nullable_NativeModuleBaseTypeAnnotation extends NativeModuleArrayTypeAnnotation<Nullable<NativeModuleBaseTypeAnnotation>> {
export interface NativeModuleStringTypeAnnotation {
readonly type: 'StringTypeAnnotation';
}
export declare type NativeModuleBaseTypeAnnotation = NativeModuleStringTypeAnnotation | NativeModuleNumberTypeAnnotation | NativeModuleInt32TypeAnnotation | NativeModuleDoubleTypeAnnotation | NativeModuleFloatTypeAnnotation | NativeModuleBooleanTypeAnnotation | NativeModuleGenericObjectTypeAnnotation | ReservedTypeAnnotation | NativeModuleTypeAliasTypeAnnotation | NativeModuleArrayTypeAnnotation_Nullable_NativeModuleBaseTypeAnnotation | NativeModuleObjectTypeAnnotation;
export interface NativeModuleNumberTypeAnnotation {
readonly type: 'NumberTypeAnnotation';
}
export interface NativeModuleInt32TypeAnnotation {
readonly type: 'Int32TypeAnnotation';
}
export interface NativeModuleDoubleTypeAnnotation {
readonly type: 'DoubleTypeAnnotation';
}
export interface NativeModuleFloatTypeAnnotation {
readonly type: 'FloatTypeAnnotation';
}
export interface NativeModuleBooleanTypeAnnotation {
readonly type: 'BooleanTypeAnnotation';
}
export interface NativeModuleEnumDeclaration {
readonly type: 'EnumDeclaration';
readonly memberType: 'NumberTypeAnnotation' | 'StringTypeAnnotation';
}
export interface NativeModuleGenericObjectTypeAnnotation {
readonly type: 'GenericObjectTypeAnnotation';
}
export interface NativeModuleTypeAliasTypeAnnotation {
readonly type: 'TypeAliasTypeAnnotation';
readonly name: string;
}
export interface NativeModulePromiseTypeAnnotation {
readonly type: 'PromiseTypeAnnotation';
}
export declare type UnionTypeAnnotationMemberType = 'NumberTypeAnnotation' | 'ObjectTypeAnnotation' | 'StringTypeAnnotation';
export interface NativeModuleUnionTypeAnnotation {
readonly type: 'UnionTypeAnnotation';
readonly memberType: UnionTypeAnnotationMemberType;
}
export interface NativeModuleMixedTypeAnnotation {
readonly type: 'MixedTypeAnnotation';
}
export declare type NativeModuleBaseTypeAnnotation = NativeModuleStringTypeAnnotation | NativeModuleNumberTypeAnnotation | NativeModuleInt32TypeAnnotation | NativeModuleDoubleTypeAnnotation | NativeModuleFloatTypeAnnotation | NativeModuleBooleanTypeAnnotation | NativeModuleEnumDeclaration | NativeModuleGenericObjectTypeAnnotation | ReservedTypeAnnotation | NativeModuleTypeAliasTypeAnnotation | NativeModuleArrayTypeAnnotation<Nullable<NativeModuleBaseTypeAnnotation>> | NativeModuleObjectTypeAnnotation | NativeModuleUnionTypeAnnotation | NativeModuleMixedTypeAnnotation;
export declare type NativeModuleParamTypeAnnotation = NativeModuleBaseTypeAnnotation | NativeModuleParamOnlyTypeAnnotation;

@@ -183,0 +187,0 @@ export declare type NativeModuleReturnTypeAnnotation = NativeModuleBaseTypeAnnotation | NativeModuleReturnOnlyTypeAnnotation;

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Automatically generated from react-native/packages/react-native-codegen/src/CodegenSchema.js
// Targeting react-native 0.66-stable
// Targeting react-native 1000.0.0
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=CodegenSchema.js.map

@@ -14,3 +14,10 @@ import { SchemaType } from './CodegenSchema';

declare type GeneratePrototype = (options: Options, config: Config) => boolean;
interface ParserModule {
parseFile(filename: string): SchemaType;
parseModuleFixture(filename: string): SchemaType;
parseString(contents: string, filename: string): SchemaType;
}
export declare const generate: GeneratePrototype;
export declare const flowParser: ParserModule;
export declare const typeScriptParser: ParserModule;
export {};

@@ -5,4 +5,6 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.generate = void 0;
exports.typeScriptParser = exports.flowParser = exports.generate = void 0;
exports.generate = (require('./rncodegen/src/generators/RNCodegen.js').generate);
exports.flowParser = (require('./rncodegen/src/parsers/flow/index.js'));
exports.typeScriptParser = (require('./rncodegen/src/parsers/typescript/index.js'));
//# sourceMappingURL=ExportRNCodegen.js.map

@@ -1,5 +0,5 @@

import * as cs from './CodegenSchema';
export declare function typeScriptToCodeSchema(fileName: string, moduleName: string, targetName?: string): cs.SchemaType;
export * from './CodegenSchema';
import * as rncodegen from './ExportRNCodegen';
export import flowParser = rncodegen.flowParser;
export import typeScriptParser = rncodegen.typeScriptParser;
export declare namespace generator {

@@ -6,0 +6,0 @@ export import generate = rncodegen.generate;

@@ -6,3 +6,7 @@ "use strict";

if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -16,123 +20,7 @@ if (k2 === undefined) k2 = k;

Object.defineProperty(exports, "__esModule", { value: true });
exports.generator = exports.typeScriptToCodeSchema = void 0;
var path = require("path");
var ts = require("typescript");
var ComponentParser_1 = require("./ComponentParser");
var ep = require("./ExportParser");
var NativeModuleParser_1 = require("./NativeModuleParser");
var TypeChecker_1 = require("./TypeChecker");
function messageChainToString(chain, indent) {
var message = '';
message += "" + indent + chain.messageText;
if (chain.next !== undefined) {
message += " {";
var newIndent = indent + " ";
for (var _i = 0, _a = chain.next; _i < _a.length; _i++) {
var subChain = _a[_i];
message += "\r\n" + messageChainToString(subChain, newIndent);
}
message += indent + "\r\n}";
}
return message;
}
function errorToString(error) {
var message = ts.DiagnosticCategory[error.category] + ":";
if (error.source !== undefined) {
message += "\r\n source : " + error.source;
}
if (error.file !== undefined) {
message += "\r\n file : " + error.file.fileName;
}
if (typeof error.messageText === 'string') {
message += "\r\n message : " + error.messageText;
}
else {
message += "\r\n message {";
message += "\r\n" + messageChainToString(error.messageText, ' ');
message += "\r\n}";
}
return message;
}
function typeScriptToCodeSchema(fileName, moduleName, targetName) {
var program = ts.createProgram([fileName], {
strictNullChecks: true,
skipLibCheck: true
});
var errors = ts.getPreEmitDiagnostics(program).filter(function (value) { return value.category === ts.DiagnosticCategory.Error; });
if (errors.length > 0) {
var errorMessage = 'Please ensure that the input TypeScript source file compiles.';
for (var _i = 0, errors_1 = errors; _i < errors_1.length; _i++) {
var error = errors_1[_i];
errorMessage += "\r\n" + errorToString(error);
}
throw new Error(errorMessage);
}
var nativeModuleInfos = [];
var componentInfos = [];
var commandInfos = [];
program.getSourceFiles().forEach(function (sourceFile) {
if (path.basename(fileName) === path.basename(sourceFile.fileName)) {
sourceFile.statements.forEach(function (node) {
var currentNativeModuleInfo = ep.tryParseExportNativeModule(program, sourceFile, node);
var currentComponentInfo = ep.tryParseExportComponent(program, sourceFile, node);
var currentCommandInfo = ep.tryParseExportCommand(program, sourceFile, node);
if (currentNativeModuleInfo !== undefined) {
nativeModuleInfos.push(currentNativeModuleInfo);
}
if (currentComponentInfo !== undefined) {
componentInfos.push(currentComponentInfo);
}
if (currentCommandInfo !== undefined) {
commandInfos.push(currentCommandInfo);
}
});
}
});
if (nativeModuleInfos.length + componentInfos.length === 0) {
throw new Error('Cannot find any component or native module.');
}
if (nativeModuleInfos.length + componentInfos.length > 1) {
throw new Error('A TypeScript source file should only container either one component or one native module.');
}
if (nativeModuleInfos.length === 1) {
if (commandInfos.length > 0) {
throw new Error('Command list should not be exported in a TypeScript source file that exports a native module.');
}
// find out all type aliases in this file
var aliases_1 = { aliases: {} };
var knownAliases_1 = [];
program.getSourceFiles().forEach(function (sourceFile) {
if (path.basename(fileName) === path.basename(sourceFile.fileName)) {
sourceFile.statements.forEach(function (node) {
if (ts.isTypeAliasDeclaration(node)) {
if (node.typeParameters === undefined || node.typeParameters.length === 0) {
var rnRawType = TypeChecker_1.typeToRNRawType(node.type, sourceFile, { allowObject: true, knownAliases: knownAliases_1 });
if (rnRawType.kind === 'Object') {
var aliasName = node.name.text;
aliases_1.aliases[aliasName] = rnRawType;
knownAliases_1.push(aliasName);
}
}
}
});
}
});
var info = nativeModuleInfos[0];
var result = { modules: {} };
result.modules[moduleName] = NativeModuleParser_1.processNativeModule(info, aliases_1);
return result;
}
else {
if (commandInfos.length > 1) {
throw new Error('A TypeScript source file should not export more than one command list.');
}
var info = componentInfos[0];
var result = { modules: {} };
result.modules[info.name] = ComponentParser_1.processComponent(info, commandInfos[0]);
return result;
}
}
exports.typeScriptToCodeSchema = typeScriptToCodeSchema;
exports.generator = exports.typeScriptParser = exports.flowParser = void 0;
__exportStar(require("./CodegenSchema"), exports);
var rncodegen = require("./ExportRNCodegen");
exports.flowParser = rncodegen.flowParser;
exports.typeScriptParser = rncodegen.typeScriptParser;
var generator;

@@ -139,0 +27,0 @@ (function (generator) {

/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -22,17 +22,27 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const babel = require('@babel/core');
const chalk = require('chalk');
const fs = require('fs');
const glob = require('glob');
const micromatch = require('micromatch');
const mkdirp = require('mkdirp');
const path = require('path');
const prettier = require('prettier');
const prettierConfig = JSON.parse(
fs.readFileSync(path.resolve(__dirname, '..', '.prettierrc'), 'utf8'),
);
const prettierConfig = JSON.parse(fs.readFileSync(path.resolve(__dirname, '..', '.prettierrc'), 'utf8'));
const SRC_DIR = 'src';

@@ -48,9 +58,8 @@ const BUILD_DIR = 'lib';

let lastString = strs[strs.length - 1];
if (lastString.length < WIDTH) {
lastString += Array(WIDTH - lastString.length).join(chalk.dim('.'));
}
return strs
.slice(0, -1)
.concat(lastString)
.join('\n');
return strs.slice(0, -1).concat(lastString).join('\n');
};

@@ -67,43 +76,21 @@

const destPath = getBuildPath(file, BUILD_DIR);
mkdirp.sync(path.dirname(destPath));
mkdirp.sync(path.dirname(destPath));
if (micromatch.isMatch(file, IGNORE_PATTERN)) {
silent ||
process.stdout.write(
chalk.dim(' \u2022 ') +
path.relative(PACKAGE_DIR, file) +
' (ignore)\n',
);
silent || process.stdout.write(chalk.dim(' \u2022 ') + path.relative(PACKAGE_DIR, file) + ' (ignore)\n');
} else if (!micromatch.isMatch(file, JS_FILES_PATTERN)) {
fs.createReadStream(file).pipe(fs.createWriteStream(destPath));
silent ||
process.stdout.write(
chalk.red(' \u2022 ') +
path.relative(PACKAGE_DIR, file) +
chalk.red(' \u21D2 ') +
path.relative(PACKAGE_DIR, destPath) +
' (copy)' +
'\n',
);
silent || process.stdout.write(chalk.red(' \u2022 ') + path.relative(PACKAGE_DIR, file) + chalk.red(' \u21D2 ') + path.relative(PACKAGE_DIR, destPath) + ' (copy)' + '\n');
} else {
const transformed = prettier.format(
babel.transformFileSync(file, {}).code,
{
...prettierConfig,
parser: 'babel',
},
);
const transformed = prettier.format(babel.transformFileSync(file, {}).code, _objectSpread({}, prettierConfig, {
parser: 'babel'
}));
fs.writeFileSync(destPath, transformed);
const source = fs.readFileSync(file).toString('utf-8');
if (/\ /.test(source)) {
if (/ /.test(source)) {
fs.createReadStream(file).pipe(fs.createWriteStream(destPath + '.flow'));
}
silent ||
process.stdout.write(
chalk.green(' \u2022 ') +
path.relative(PACKAGE_DIR, file) +
chalk.green(' \u21D2 ') +
path.relative(PACKAGE_DIR, destPath) +
'\n',
);
silent || process.stdout.write(chalk.green(' \u2022 ') + path.relative(PACKAGE_DIR, file) + chalk.green(' \u21D2 ') + path.relative(PACKAGE_DIR, destPath) + '\n');
}

@@ -114,8 +101,7 @@ }

const pattern = path.resolve(srcDir, '**/*');
const files = glob.sync(pattern, {nodir: true});
const files = glob.sync(pattern, {
nodir: true
});
process.stdout.write(fixedWidth(`${path.basename(PACKAGE_DIR)}\n`));
files.forEach(file => buildFile(file, !process.argv.includes('--verbose')));
process.stdout.write(`[ ${chalk.green('OK')} ]\n`);
process.stdout.write(`[ ${chalk.green('OK')} ]\n`);
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,319 +10,9 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
/**
* Component Type Annotations
*/
/**
* NativeModule Types
*/
*/
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,7 +10,5 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function upperCaseFirst(inString ) {
function upperCaseFirst(inString) {
if (inString.length === 0) {

@@ -23,34 +21,29 @@ return inString;

function toSafeCppString(input ) {
return input
.split('-')
.map(upperCaseFirst)
.join('');
function toSafeCppString(input) {
return input.split('-').map(upperCaseFirst).join('');
}
function toIntEnumValueName(propName , value ) {
function toIntEnumValueName(propName, value) {
return `${toSafeCppString(propName)}${value}`;
}
function getCppTypeForAnnotation(
type
,
) {
function getCppTypeForAnnotation(type) {
switch (type) {
case 'BooleanTypeAnnotation':
return 'bool';
case 'StringTypeAnnotation':
return 'std::string';
case 'Int32TypeAnnotation':
return 'int';
case 'DoubleTypeAnnotation':
return 'double';
case 'FloatTypeAnnotation':
return 'Float';
default:
(type );
type;
throw new Error(`Received invalid typeAnnotation ${type}`);

@@ -60,6 +53,4 @@ }

function getImports(
properties ,
) {
const imports = new Set();
function getImports(properties) {
const imports = new Set();

@@ -70,11 +61,18 @@ function addImportsForNativeName(name) {

return;
case 'PointPrimitive':
return;
case 'EdgeInsetsPrimitive':
return;
case 'ImageRequestPrimitive':
return;
case 'ImageSourcePrimitive':
imports.add('#include <react/renderer/components/image/conversions.h>');
return;
default:
(name );
name;
throw new Error(`Invalid name, got ${name}`);

@@ -91,6 +89,3 @@ }

if (
typeAnnotation.type === 'ArrayTypeAnnotation' &&
typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation'
) {
if (typeAnnotation.type === 'ArrayTypeAnnotation' && typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation') {
addImportsForNativeName(typeAnnotation.elementType.name);

@@ -100,12 +95,11 @@ }

if (typeAnnotation.type === 'ObjectTypeAnnotation') {
const objectImports = getImports(typeAnnotation.properties);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
const objectImports = getImports(typeAnnotation.properties); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
objectImports.forEach(imports.add, imports);
}
});
return imports;
}
function generateEventStructName(parts = []) {
function generateEventStructName(parts = []) {
const additional = parts.map(toSafeCppString).join('');

@@ -115,6 +109,3 @@ return `${additional}`;

function generateStructName(
componentName ,
parts = [],
) {
function generateStructName(componentName, parts = []) {
const additional = parts.map(toSafeCppString).join('');

@@ -124,3 +115,3 @@ return `${componentName}${additional}Struct`;

function getEnumName(componentName , propName ) {
function getEnumName(componentName, propName) {
const uppercasedPropName = toSafeCppString(propName);

@@ -130,11 +121,9 @@ return `${componentName}${uppercasedPropName}`;

function getEnumMaskName(enumName ) {
function getEnumMaskName(enumName) {
return `${enumName}Mask`;
}
function convertDefaultTypeToString(
componentName ,
prop ,
) {
function convertDefaultTypeToString(componentName, prop) {
const typeAnnotation = prop.typeAnnotation;
switch (typeAnnotation.type) {

@@ -145,3 +134,5 @@ case 'BooleanTypeAnnotation':

}
return String(typeAnnotation.default);
case 'StringTypeAnnotation':

@@ -151,18 +142,21 @@ if (typeAnnotation.default == null) {

}
return `"${typeAnnotation.default}"`;
case 'Int32TypeAnnotation':
return String(typeAnnotation.default);
case 'DoubleTypeAnnotation':
const defaultDoubleVal = typeAnnotation.default;
return parseInt(defaultDoubleVal, 10) === defaultDoubleVal
? typeAnnotation.default.toFixed(1)
: String(typeAnnotation.default);
return parseInt(defaultDoubleVal, 10) === defaultDoubleVal ? typeAnnotation.default.toFixed(1) : String(typeAnnotation.default);
case 'FloatTypeAnnotation':
const defaultFloatVal = typeAnnotation.default;
if (defaultFloatVal == null) {
return '';
}
return parseInt(defaultFloatVal, 10) === defaultFloatVal
? defaultFloatVal.toFixed(1)
: String(typeAnnotation.default);
return parseInt(defaultFloatVal, 10) === defaultFloatVal ? defaultFloatVal.toFixed(1) : String(typeAnnotation.default);
case 'ReservedPropTypeAnnotation':

@@ -172,47 +166,53 @@ switch (typeAnnotation.name) {

return '';
case 'ImageSourcePrimitive':
return '';
case 'ImageRequestPrimitive':
return '';
case 'PointPrimitive':
return '';
case 'EdgeInsetsPrimitive':
return '';
default:
(typeAnnotation.name );
throw new Error(
`Unsupported type annotation: ${typeAnnotation.name}`,
);
typeAnnotation.name;
throw new Error(`Unsupported type annotation: ${typeAnnotation.name}`);
}
case 'ArrayTypeAnnotation': {
const elementType = typeAnnotation.elementType;
switch (elementType.type) {
case 'StringEnumTypeAnnotation':
if (elementType.default == null) {
throw new Error(
'A default is required for array StringEnumTypeAnnotation',
);
}
const enumName = getEnumName(componentName, prop.name);
const enumMaskName = getEnumMaskName(enumName);
const defaultValue = `${enumName}::${toSafeCppString(
elementType.default,
)}`;
return `static_cast<${enumMaskName}>(${defaultValue})`;
default:
return '';
case 'ArrayTypeAnnotation':
{
const elementType = typeAnnotation.elementType;
switch (elementType.type) {
case 'StringEnumTypeAnnotation':
if (elementType.default == null) {
throw new Error('A default is required for array StringEnumTypeAnnotation');
}
const enumName = getEnumName(componentName, prop.name);
const enumMaskName = getEnumMaskName(enumName);
const defaultValue = `${enumName}::${toSafeCppString(elementType.default)}`;
return `static_cast<${enumMaskName}>(${defaultValue})`;
default:
return '';
}
}
}
case 'ObjectTypeAnnotation': {
return '';
}
case 'ObjectTypeAnnotation':
{
return '';
}
case 'StringEnumTypeAnnotation':
return `${getEnumName(componentName, prop.name)}::${toSafeCppString(
typeAnnotation.default,
)}`;
return `${getEnumName(componentName, prop.name)}::${toSafeCppString(typeAnnotation.default)}`;
case 'Int32EnumTypeAnnotation':
return `${getEnumName(componentName, prop.name)}::${toIntEnumValueName(
prop.name,
typeAnnotation.default,
)}`;
return `${getEnumName(componentName, prop.name)}::${toIntEnumValueName(prop.name, typeAnnotation.default)}`;
default:
(typeAnnotation );
typeAnnotation;
throw new Error(`Unsupported type annotation: ${typeAnnotation.type}`);

@@ -231,3 +231,3 @@ }

generateStructName,
generateEventStructName,
};
generateEventStructName
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,16 +10,13 @@ * This source code is licensed under the MIT license found in the

*/
'use strict'; // File path -> contents
'use strict';
// File path -> contents
const template = `
const FileTemplate = ({
componentDescriptors,
libraryName
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -31,3 +28,3 @@ * ${'@'}generated by codegen project: GenerateComponentDescriptorH.js

#include <react/renderer/components/::_LIBRARY_::/ShadowNodes.h>
#include <react/renderer/components/${libraryName}/ShadowNodes.h>
#include <react/renderer/core/ConcreteComponentDescriptor.h>

@@ -38,3 +35,3 @@

::_COMPONENT_DESCRIPTORS_::
${componentDescriptors}

@@ -45,46 +42,41 @@ } // namespace react

const componentTemplate = `
using ::_CLASSNAME_::ComponentDescriptor = ConcreteComponentDescriptor<::_CLASSNAME_::ShadowNode>;
const ComponentTemplate = ({
className
}) => `
using ${className}ComponentDescriptor = ConcreteComponentDescriptor<${className}ShadowNode>;
`.trim();
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'ComponentDescriptors.h';
const componentDescriptors = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const componentDescriptors = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
const components = module.components; // No components in this module
return Object.keys(components)
.map(componentName => {
if (components[componentName].interfaceOnly === true) {
return;
}
return componentTemplate.replace(/::_CLASSNAME_::/g, componentName);
})
.join('\n');
})
.filter(Boolean)
.join('\n');
if (components == null) {
return null;
}
const replacedTemplate = template
.replace(/::_COMPONENT_DESCRIPTORS_::/g, componentDescriptors)
.replace('::_LIBRARY_::', libraryName);
return Object.keys(components).map(componentName => {
if (components[componentName].interfaceOnly === true) {
return;
}
return ComponentTemplate({
className: componentName
});
}).join('\n');
}).filter(Boolean).join('\n');
const replacedTemplate = FileTemplate({
componentDescriptors,
libraryName
});
return new Map([[fileName, replacedTemplate]]);
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,21 +10,12 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function getOrdinalNumber(num ) {
function getOrdinalNumber(num) {
switch (num) {
case 1:
return '1st';
case 2:
return '2nd';
case 3:

@@ -41,23 +32,39 @@ return '3rd';

const protocolTemplate = `
@protocol RCT::_COMPONENT_NAME_::ViewProtocol <NSObject>
::_METHODS_::
const ProtocolTemplate = ({
componentName,
methods
}) => `
@protocol RCT${componentName}ViewProtocol <NSObject>
${methods}
@end
`.trim();
const commandHandlerIfCaseConvertArgTemplate = `
NSObject *arg::_ARG_NUMBER_:: = args[::_ARG_NUMBER_::];
const CommandHandlerIfCaseConvertArgTemplate = ({
componentName,
expectedKind,
argNumber,
argNumberString,
expectedKindString,
argConversion
}) => `
NSObject *arg${argNumber} = args[${argNumber}];
#if RCT_DEBUG
if (!RCTValidateTypeOfViewCommandArgument(arg::_ARG_NUMBER_::, ::_EXPECTED_KIND_::, @"::_EXPECTED_KIND_STRING_::", @"::_COMPONENT_NAME_::", commandName, @"::_ARG_NUMBER_STR_::")) {
if (!RCTValidateTypeOfViewCommandArgument(arg${argNumber}, ${expectedKind}, @"${expectedKindString}", @"${componentName}", commandName, @"${argNumberString}")) {
return;
}
#endif
::_ARG_CONVERSION_::
${argConversion}
`.trim();
const commandHandlerIfCaseTemplate = `
if ([commandName isEqualToString:@"::_COMMAND_NAME_::"]) {
const CommandHandlerIfCaseTemplate = ({
componentName,
commandName,
numArgs,
convertArgs,
commandCall
}) => `
if ([commandName isEqualToString:@"${commandName}"]) {
#if RCT_DEBUG
if ([args count] != ::_NUM_ARGS_::) {
RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"::_COMPONENT_NAME_::", commandName, (int)[args count], ::_NUM_ARGS_::);
if ([args count] != ${numArgs}) {
RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"${componentName}", commandName, (int)[args count], ${numArgs});
return;

@@ -67,5 +74,5 @@ }

::_CONVERT_ARGS_::
${convertArgs}
::_COMMAND_CALL_::
${commandCall}
return;

@@ -75,12 +82,15 @@ }

const commandHandlerTemplate = `
RCT_EXTERN inline void RCT::_COMPONENT_NAME_::HandleCommand(
id<RCT::_COMPONENT_NAME_::ViewProtocol> componentView,
const CommandHandlerTemplate = ({
componentName,
ifCases
}) => `
RCT_EXTERN inline void RCT${componentName}HandleCommand(
id<RCT${componentName}ViewProtocol> componentView,
NSString const *commandName,
NSArray const *args)
{
::_IF_CASES_::
${ifCases}
#if RCT_DEBUG
RCTLogError(@"%@ received command %@, which is not a supported command.", @"::_COMPONENT_NAME_::", commandName);
RCTLogError(@"%@ received command %@, which is not a supported command.", @"${componentName}", commandName);
#endif

@@ -90,8 +100,10 @@ }

const template = `
const FileTemplate = ({
componentContent
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -107,3 +119,3 @@ * ${'@'}generated by codegen project: GenerateComponentHObjCpp.js

::_COMPONENT_CONTENT_::
${componentContent}

@@ -113,7 +125,5 @@ NS_ASSUME_NONNULL_END

function getObjCParamType(param) {
const typeAnnotation = param.typeAnnotation;
function getObjCParamType(param ) {
const {typeAnnotation} = param;
switch (typeAnnotation.type) {

@@ -124,18 +134,25 @@ case 'ReservedTypeAnnotation':

return 'double';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return 'BOOL';
case 'DoubleTypeAnnotation':
return 'double';
case 'FloatTypeAnnotation':
return 'float';
case 'Int32TypeAnnotation':
return 'NSInteger';
case 'StringTypeAnnotation':
return 'NSString *';
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error('Received invalid param type annotation');

@@ -145,4 +162,4 @@ }

function getObjCExpectedKindParamType(param ) {
const {typeAnnotation} = param;
function getObjCExpectedKindParamType(param) {
const typeAnnotation = param.typeAnnotation;

@@ -154,18 +171,25 @@ switch (typeAnnotation.type) {

return '[NSNumber class]';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return '[NSNumber class]';
case 'DoubleTypeAnnotation':
return '[NSNumber class]';
case 'FloatTypeAnnotation':
return '[NSNumber class]';
case 'Int32TypeAnnotation':
return '[NSNumber class]';
case 'StringTypeAnnotation':
return '[NSString class]';
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error('Received invalid param type annotation');

@@ -175,4 +199,4 @@ }

function getReadableExpectedKindParamType(param ) {
const {typeAnnotation} = param;
function getReadableExpectedKindParamType(param) {
const typeAnnotation = param.typeAnnotation;

@@ -184,18 +208,25 @@ switch (typeAnnotation.type) {

return 'double';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return 'boolean';
case 'DoubleTypeAnnotation':
return 'double';
case 'FloatTypeAnnotation':
return 'float';
case 'Int32TypeAnnotation':
return 'number';
case 'StringTypeAnnotation':
return 'string';
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error('Received invalid param type annotation');

@@ -205,7 +236,4 @@ }

function getObjCRightHandAssignmentParamType(
param ,
index ,
) {
const {typeAnnotation} = param;
function getObjCRightHandAssignmentParamType(param, index) {
const typeAnnotation = param.typeAnnotation;

@@ -217,18 +245,25 @@ switch (typeAnnotation.type) {

return `[(NSNumber *)arg${index} doubleValue]`;
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return `[(NSNumber *)arg${index} boolValue]`;
case 'DoubleTypeAnnotation':
return `[(NSNumber *)arg${index} doubleValue]`;
case 'FloatTypeAnnotation':
return `[(NSNumber *)arg${index} floatValue]`;
case 'Int32TypeAnnotation':
return `[(NSNumber *)arg${index} intValue]`;
case 'StringTypeAnnotation':
return `(NSString *)arg${index}`;
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error('Received invalid param type annotation');

@@ -238,87 +273,49 @@ }

function generateProtocol(
component ,
componentName ,
) {
const commands = component.commands
.map(command => {
const params = command.typeAnnotation.params;
const paramString =
params.length === 0
? ''
: params
.map((param, index) => {
const objCType = getObjCParamType(param);
return `${index === 0 ? '' : param.name}:(${objCType})${
param.name
}`;
})
.join(' ');
return `- (void)${command.name}${paramString};`;
})
.join('\n')
.trim();
return protocolTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace('::_METHODS_::', commands);
function generateProtocol(component, componentName) {
const methods = component.commands.map(command => {
const params = command.typeAnnotation.params;
const paramString = params.length === 0 ? '' : params.map((param, index) => {
const objCType = getObjCParamType(param);
return `${index === 0 ? '' : param.name}:(${objCType})${param.name}`;
}).join(' ');
return `- (void)${command.name}${paramString};`;
}).join('\n').trim();
return ProtocolTemplate({
componentName,
methods
});
}
function generateConvertAndValidateParam(
param ,
index ,
componentName ,
) {
function generateConvertAndValidateParam(param, index, componentName) {
const leftSideType = getObjCParamType(param);
const expectedKind = getObjCExpectedKindParamType(param);
const expectedKindString = getReadableExpectedKindParamType(param);
const argConversion = `${leftSideType} ${
param.name
} = ${getObjCRightHandAssignmentParamType(param, index)};`;
return commandHandlerIfCaseConvertArgTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace('::_ARG_CONVERSION_::', argConversion)
.replace(/::_ARG_NUMBER_::/g, '' + index)
.replace('::_ARG_NUMBER_STR_::', getOrdinalNumber(index + 1))
.replace('::_EXPECTED_KIND_::', expectedKind)
.replace('::_EXPECTED_KIND_STRING_::', expectedKindString);
const argConversion = `${leftSideType} ${param.name} = ${getObjCRightHandAssignmentParamType(param, index)};`;
return CommandHandlerIfCaseConvertArgTemplate({
componentName,
argConversion,
argNumber: index,
argNumberString: getOrdinalNumber(index + 1),
expectedKind,
expectedKindString
});
}
function generateCommandIfCase(
command ,
componentName ,
) {
function generateCommandIfCase(command, componentName) {
const params = command.typeAnnotation.params;
const convertArgs = params
.map((param, index) =>
generateConvertAndValidateParam(param, index, componentName),
)
.join('\n\n')
.trim();
const commandCallArgs =
params.length === 0
? ''
: params
.map((param, index) => {
return `${index === 0 ? '' : param.name}:${param.name}`;
})
.join(' ');
const convertArgs = params.map((param, index) => generateConvertAndValidateParam(param, index, componentName)).join('\n\n').trim();
const commandCallArgs = params.length === 0 ? '' : params.map((param, index) => {
return `${index === 0 ? '' : param.name}:${param.name}`;
}).join(' ');
const commandCall = `[componentView ${command.name}${commandCallArgs}];`;
return commandHandlerIfCaseTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace(/::_COMMAND_NAME_::/g, command.name)
.replace(/::_NUM_ARGS_::/g, '' + params.length)
.replace('::_CONVERT_ARGS_::', convertArgs)
.replace('::_COMMAND_CALL_::', commandCall);
return CommandHandlerIfCaseTemplate({
componentName,
commandName: command.name,
numArgs: params.length,
convertArgs,
commandCall
});
}
function generateCommandHandler(
component ,
componentName ,
) {
function generateCommandHandler(component, componentName) {
if (component.commands.length === 0) {

@@ -328,61 +325,38 @@ return null;

const ifCases = component.commands
.map(command => generateCommandIfCase(command, componentName))
.join('\n\n');
return commandHandlerTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace('::_IF_CASES_::', ifCases);
const ifCases = component.commands.map(command => generateCommandIfCase(command, componentName)).join('\n\n');
return CommandHandlerTemplate({
componentName,
ifCases
});
}
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'RCTComponentViewHelpers.h';
const componentContent = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const componentContent = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
const components = module.components; // No components in this module
return Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})
.map(componentName => {
return [
generateProtocol(components[componentName], componentName),
generateCommandHandler(components[componentName], componentName),
]
.join('\n\n')
.trim();
})
.join('\n\n');
})
.filter(Boolean)
.join('\n\n');
if (components == null) {
return null;
}
const replacedTemplate = template.replace(
'::_COMPONENT_CONTENT_::',
componentContent,
);
return Object.keys(components).filter(componentName => {
const component = components[componentName];
return !(component.excludedPlatforms && component.excludedPlatforms.includes('iOS'));
}).map(componentName => {
return [generateProtocol(components[componentName], componentName), generateCommandHandler(components[componentName], componentName)].join('\n\n').trim();
}).join('\n\n');
}).filter(Boolean).join('\n\n');
const replacedTemplate = FileTemplate({
componentContent
});
return new Map([[fileName, replacedTemplate]]);
}
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,28 +10,17 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {generateEventStructName} = require('./CppHelpers.js');
const _require = require('./CppHelpers.js'),
generateEventStructName = _require.generateEventStructName; // File path -> contents
// File path -> contents
const template = `
const FileTemplate = ({
events,
libraryName
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -41,3 +30,3 @@ * ${'@'}generated by codegen project: GenerateEventEmitterCpp.js

#include <react/renderer/components/::_LIBRARY_::/EventEmitters.h>
#include <react/renderer/components/${libraryName}/EventEmitters.h>

@@ -47,3 +36,3 @@ namespace facebook {

::_EVENTS_::
${events}

@@ -54,6 +43,12 @@ } // namespace react

const componentTemplate = `
void ::_CLASSNAME_::EventEmitter::::_EVENT_NAME_::(::_STRUCT_NAME_:: event) const {
dispatchEvent("::_DISPATCH_EVENT_NAME_::", [event=std::move(event)](jsi::Runtime &runtime) {
::_IMPLEMENTATION_::
const ComponentTemplate = ({
className,
eventName,
structName,
dispatchEventName,
implementation
}) => `
void ${className}EventEmitter::${eventName}(${structName} event) const {
dispatchEvent("${dispatchEventName}", [event=std::move(event)](jsi::Runtime &runtime) {
${implementation}
});

@@ -63,5 +58,9 @@ }

const basicComponentTemplate = `
void ::_CLASSNAME_::EventEmitter::::_EVENT_NAME_::() const {
dispatchEvent("::_DISPATCH_EVENT_NAME_::");
const BasicComponentTemplate = ({
className,
eventName,
dispatchEventName
}) => `
void ${className}EventEmitter::${eventName}() const {
dispatchEvent("${dispatchEventName}");
}

@@ -72,6 +71,3 @@ `.trim();

const trailingPeriod = propertyParts.length === 0 ? '' : '.';
const eventChain = `event.${propertyParts.join(
'.',
)}${trailingPeriod}${propertyName});`;
const eventChain = `event.${propertyParts.join('.')}${trailingPeriod}${propertyName});`;
return `${variableName}.setProperty(runtime, "${propertyName}", ${eventChain}`;

@@ -82,64 +78,35 @@ }

const trailingPeriod = propertyParts.length === 0 ? '' : '.';
const eventChain = `event.${propertyParts.join(
'.',
)}${trailingPeriod}${propertyName})`;
const eventChain = `event.${propertyParts.join('.')}${trailingPeriod}${propertyName})`;
return `${variableName}.setProperty(runtime, "${propertyName}", toString(${eventChain});`;
}
function generateSetters(
parentPropertyName ,
properties ,
propertyParts ,
) {
const propSetters = properties
.map(eventProperty => {
const {typeAnnotation} = eventProperty;
switch (typeAnnotation.type) {
case 'BooleanTypeAnnotation':
return generateSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'StringTypeAnnotation':
return generateSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'Int32TypeAnnotation':
return generateSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'DoubleTypeAnnotation':
return generateSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'FloatTypeAnnotation':
return generateSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'StringEnumTypeAnnotation':
return generateEnumSetter(
parentPropertyName,
eventProperty.name,
propertyParts,
);
case 'ObjectTypeAnnotation':
const propertyName = eventProperty.name;
return `
function generateSetters(parentPropertyName, properties, propertyParts) {
const propSetters = properties.map(eventProperty => {
const typeAnnotation = eventProperty.typeAnnotation;
switch (typeAnnotation.type) {
case 'BooleanTypeAnnotation':
return generateSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'StringTypeAnnotation':
return generateSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'Int32TypeAnnotation':
return generateSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'DoubleTypeAnnotation':
return generateSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'FloatTypeAnnotation':
return generateSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'StringEnumTypeAnnotation':
return generateEnumSetter(parentPropertyName, eventProperty.name, propertyParts);
case 'ObjectTypeAnnotation':
const propertyName = eventProperty.name;
return `
{
auto ${propertyName} = jsi::Object(runtime);
${generateSetters(
propertyName,
typeAnnotation.properties,
propertyParts.concat([propertyName]),
)}
${generateSetters(propertyName, typeAnnotation.properties, propertyParts.concat([propertyName]))}

@@ -149,13 +116,12 @@ ${parentPropertyName}.setProperty(runtime, "${propertyName}", ${propertyName});

`.trim();
default:
(typeAnnotation.type );
throw new Error('Received invalid event property type');
}
})
.join('\n');
default:
typeAnnotation.type;
throw new Error('Received invalid event property type');
}
}).join('\n');
return propSetters;
}
function generateEvent(componentName , event) {
function generateEvent(componentName, event) {
// This is a gross hack necessary because native code is sending

@@ -167,5 +133,3 @@ // events named things like topChange to JS which is then converted back to

// throughout the system.
const dispatchEventName = `${event.name[2].toLowerCase()}${event.name.slice(
3,
)}`;
const dispatchEventName = `${event.name[2].toLowerCase()}${event.name.slice(3)}`;

@@ -183,62 +147,49 @@ if (event.typeAnnotation.argument) {

return componentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace(/::_EVENT_NAME_::/g, event.name)
.replace(/::_DISPATCH_EVENT_NAME_::/g, dispatchEventName)
.replace('::_STRUCT_NAME_::', generateEventStructName([event.name]))
.replace('::_IMPLEMENTATION_::', implementation);
return ComponentTemplate({
className: componentName,
eventName: event.name,
dispatchEventName,
structName: generateEventStructName([event.name]),
implementation
});
}
return basicComponentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace(/::_EVENT_NAME_::/g, event.name)
.replace(/::_DISPATCH_EVENT_NAME_::/g, dispatchEventName);
return BasicComponentTemplate({
className: componentName,
eventName: event.name,
dispatchEventName
});
}
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
const moduleComponents = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
generate(libraryName, schema, packageName, assumeNonnull = false) {
const moduleComponents = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
if (module.type !== 'Component') {
return;
}
return components;
})
.filter(Boolean)
.reduce((acc, components) => Object.assign(acc, components), {});
const components = module.components; // No components in this module
if (components == null) {
return null;
}
return components;
}).filter(Boolean).reduce((acc, components) => Object.assign(acc, components), {});
const fileName = 'EventEmitters.cpp';
const componentEmitters = Object.keys(moduleComponents).map(componentName => {
const component = moduleComponents[componentName];
return component.events.map(event => {
return generateEvent(componentName, event);
}).join('\n');
}).join('\n');
const replacedTemplate = FileTemplate({
libraryName,
events: componentEmitters
});
return new Map([[fileName, replacedTemplate]]);
}
const componentEmitters = Object.keys(moduleComponents)
.map(componentName => {
const component = moduleComponents[componentName];
return component.events
.map(event => {
return generateEvent(componentName, event);
})
.join('\n');
})
.join('\n');
const replacedTemplate = template
.replace(/::_COMPONENT_EMITTERS_::/g, componentEmitters)
.replace('::_LIBRARY_::', libraryName)
.replace('::_EVENTS_::', componentEmitters);
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,3 +10,2 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';

@@ -16,31 +15,19 @@

const {
getCppTypeForAnnotation,
toSafeCppString,
generateEventStructName,
} = require('./CppHelpers.js');
const _require = require('./CppHelpers'),
getCppTypeForAnnotation = _require.getCppTypeForAnnotation,
toSafeCppString = _require.toSafeCppString,
generateEventStructName = _require.generateEventStructName;
const _require2 = require('../Utils'),
indent = _require2.indent; // File path -> contents
// File path -> contents
const template = `
const FileTemplate = ({
componentEmitters
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -52,2 +39,3 @@ * ${'@'}generated by codegen project: GenerateEventEmitterH.js

#include <react/renderer/components/view/ViewEventEmitter.h>
#include <jsi/jsi.h>

@@ -57,3 +45,3 @@ namespace facebook {

::_COMPONENT_EMITTERS_::
${componentEmitters}

@@ -64,26 +52,37 @@ } // namespace react

const componentTemplate = `
class ::_CLASSNAME_::EventEmitter : public ViewEventEmitter {
const ComponentTemplate = ({
className,
structs,
events
}) => `
class JSI_EXPORT ${className}EventEmitter : public ViewEventEmitter {
public:
using ViewEventEmitter::ViewEventEmitter;
::_STRUCTS_::
${structs}
::_EVENTS_::
${events}
};
`.trim();
const structTemplate = `
struct ::_STRUCT_NAME_:: {
::_FIELDS_::
const StructTemplate = ({
structName,
fields
}) => `
struct ${structName} {
${fields}
};
`.trim();
const enumTemplate = `enum class ::_ENUM_NAME_:: {
::_VALUES_::
const EnumTemplate = ({
enumName,
values,
toCases
}) => `enum class ${enumName} {
${values}
};
static char const *toString(const ::_ENUM_NAME_:: value) {
static char const *toString(const ${enumName} value) {
switch (value) {
::_TO_CASES_::
${toCases}
}

@@ -93,22 +92,5 @@ }

function indent(nice , spaces ) {
return nice
.split('\n')
.map((line, index) => {
if (line.length === 0 || index === 0) {
return line;
}
const emptySpaces = new Array(spaces + 1).join(' ');
return emptySpaces + line;
})
.join('\n');
}
function getNativeTypeFromAnnotation(componentName, eventProperty, nameParts) {
const type = eventProperty.typeAnnotation.type;
function getNativeTypeFromAnnotation(
componentName ,
eventProperty ,
nameParts ,
) {
const {type} = eventProperty.typeAnnotation;
switch (type) {

@@ -121,113 +103,84 @@ case 'BooleanTypeAnnotation':

return getCppTypeForAnnotation(type);
case 'StringEnumTypeAnnotation':
return generateEventStructName(nameParts.concat([eventProperty.name]));
case 'ObjectTypeAnnotation':
return generateEventStructName(nameParts.concat([eventProperty.name]));
default:
(type );
type;
throw new Error(`Received invalid event property type ${type}`);
}
}
function generateEnum(structs, options, nameParts) {
const structName = generateEventStructName(nameParts);
const fields = options
.map((option, index) => `${toSafeCppString(option)}`)
.join(',\n ');
const toCases = options
.map(
option =>
`case ${structName}::${toSafeCppString(option)}: return "${option}";`,
)
.join('\n' + ' ');
structs.set(
structName,
enumTemplate
.replace(/::_ENUM_NAME_::/g, structName)
.replace('::_VALUES_::', fields)
.replace('::_TO_CASES_::', toCases),
);
const fields = options.map((option, index) => `${toSafeCppString(option)}`).join(',\n ');
const toCases = options.map(option => `case ${structName}::${toSafeCppString(option)}: return "${option}";`).join('\n' + ' ');
structs.set(structName, EnumTemplate({
enumName: structName,
values: fields,
toCases: toCases
}));
}
function generateStruct(
structs ,
componentName ,
nameParts ,
properties ,
) {
function generateStruct(structs, componentName, nameParts, properties) {
const structNameParts = nameParts;
const structName = generateEventStructName(structNameParts);
const fields = properties.map(property => {
return `${getNativeTypeFromAnnotation(componentName, property, structNameParts)} ${property.name};`;
}).join('\n' + ' ');
properties.forEach(property => {
const name = property.name,
typeAnnotation = property.typeAnnotation;
const fields = properties
.map(property => {
return `${getNativeTypeFromAnnotation(
componentName,
property,
structNameParts,
)} ${property.name};`;
})
.join('\n' + ' ');
properties.forEach(property => {
const {name, typeAnnotation} = property;
switch (typeAnnotation.type) {
case 'BooleanTypeAnnotation':
return;
case 'StringTypeAnnotation':
return;
case 'Int32TypeAnnotation':
return;
case 'DoubleTypeAnnotation':
return;
case 'FloatTypeAnnotation':
return;
case 'ObjectTypeAnnotation':
generateStruct(
structs,
componentName,
nameParts.concat([name]),
nullthrows(typeAnnotation.properties),
);
generateStruct(structs, componentName, nameParts.concat([name]), nullthrows(typeAnnotation.properties));
return;
case 'StringEnumTypeAnnotation':
generateEnum(structs, typeAnnotation.options, nameParts.concat([name]));
return;
default:
(typeAnnotation.type );
throw new Error(
`Received invalid event property type ${typeAnnotation.type}`,
);
typeAnnotation.type;
throw new Error(`Received invalid event property type ${typeAnnotation.type}`);
}
});
structs.set(
structs.set(structName, StructTemplate({
structName,
structTemplate
.replace('::_STRUCT_NAME_::', structName)
.replace('::_FIELDS_::', fields),
);
fields
}));
}
function generateStructs(componentName , component) {
const structs = new Map();
function generateStructs(componentName, component) {
const structs = new Map();
component.events.forEach(event => {
if (event.typeAnnotation.argument) {
generateStruct(
structs,
componentName,
[event.name],
event.typeAnnotation.argument.properties,
);
generateStruct(structs, componentName, [event.name], event.typeAnnotation.argument.properties);
}
});
return Array.from(structs.values()).join('\n\n');
}
function generateEvent(componentName , event ) {
function generateEvent(componentName, event) {
if (event.typeAnnotation.argument) {
const structName = generateEventStructName([event.name]);
return `void ${event.name}(${structName} value) const;`;

@@ -238,69 +191,41 @@ }

}
function generateEvents(componentName , component) {
return component.events
.map(event => generateEvent(componentName, event))
.join('\n\n' + ' ');
function generateEvents(componentName, component) {
return component.events.map(event => generateEvent(componentName, event)).join('\n\n' + ' ');
}
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
const moduleComponents = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
generate(libraryName, schema, packageName, assumeNonnull = false) {
const moduleComponents = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
if (module.type !== 'Component') {
return;
}
return components;
})
.filter(Boolean)
.reduce((acc, components) => Object.assign(acc, components), {});
const components = module.components; // No components in this module
const moduleComponentsWithEvents = Object.keys(moduleComponents).filter(
componentName => moduleComponents[componentName].events.length > 0,
);
if (components == null) {
return null;
}
return components;
}).filter(Boolean).reduce((acc, components) => Object.assign(acc, components), {});
const moduleComponentsWithEvents = Object.keys(moduleComponents);
const fileName = 'EventEmitters.h';
const componentEmitters = moduleComponentsWithEvents.length > 0 ? Object.keys(moduleComponents).map(componentName => {
const component = moduleComponents[componentName];
const replacedTemplate = ComponentTemplate({
className: componentName,
structs: indent(generateStructs(componentName, component), 2),
events: generateEvents(componentName, component)
});
return replacedTemplate;
}).join('\n') : '';
const replacedTemplate = FileTemplate({
componentEmitters
});
return new Map([[fileName, replacedTemplate]]);
}
const componentEmitters =
moduleComponentsWithEvents.length > 0
? Object.keys(moduleComponents)
.map(componentName => {
const component = moduleComponents[componentName];
const replacedTemplate = componentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace(
'::_STRUCTS_::',
indent(generateStructs(componentName, component), 2),
)
.replace(
'::_EVENTS_::',
generateEvents(componentName, component),
)
.trim();
return replacedTemplate;
})
.join('\n')
: '';
const replacedTemplate = template.replace(
/::_COMPONENT_EMITTERS_::/g,
componentEmitters,
);
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,17 +10,19 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {convertDefaultTypeToString, getImports} = require('./CppHelpers');
const _require = require('./CppHelpers'),
convertDefaultTypeToString = _require.convertDefaultTypeToString,
getImports = _require.getImports; // File path -> contents
// File path -> contents
const template = `
const FileTemplate = ({
libraryName,
imports,
componentClasses
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -30,4 +32,4 @@ * ${'@'}generated by codegen project: GeneratePropsCpp.js

#include <react/renderer/components/::_LIBRARY_::/Props.h>
::_IMPORTS_::
#include <react/renderer/components/${libraryName}/Props.h>
${imports}

@@ -37,3 +39,3 @@ namespace facebook {

::_COMPONENT_CLASSES_::
${componentClasses}

@@ -44,43 +46,41 @@ } // namespace react

const componentTemplate = `
::_CLASSNAME_::::::_CLASSNAME_::(
const ComponentTemplate = ({
className,
extendClasses,
props
}) => `
${className}::${className}(
const PropsParserContext &context,
const ::_CLASSNAME_:: &sourceProps,
const RawProps &rawProps):::_EXTEND_CLASSES_::
const ${className} &sourceProps,
const RawProps &rawProps):${extendClasses}
::_PROPS_::
${props}
{}
`.trim();
function generatePropsString(componentName , component ) {
return component.props
.map(prop => {
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `${prop.name}(convertRawProp(context, rawProps, "${prop.name}", sourceProps.${prop.name}, {${defaultValue}}))`;
})
.join(',\n' + ' ');
function generatePropsString(componentName, component) {
return component.props.map(prop => {
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `${prop.name}(convertRawProp(context, rawProps, "${prop.name}", sourceProps.${prop.name}, {${defaultValue}}))`;
}).join(',\n' + ' ');
}
function getClassExtendString(component) {
const extendString =
' ' +
component.extendsProps
.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'ViewProps(context, sourceProps, rawProps)';
default:
(extendProps.knownTypeName );
throw new Error('Invalid knownTypeName');
}
function getClassExtendString(component) {
const extendString = ' ' + component.extendsProps.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'ViewProps(context, sourceProps, rawProps)';
default:
(extendProps.type );
throw new Error('Invalid extended type');
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
})
.join(', ') +
`${component.props.length > 0 ? ',' : ''}`;
default:
extendProps.type;
throw new Error('Invalid extended type');
}
}).join(', ') + `${component.props.length > 0 ? ',' : ''}`;
return extendString;

@@ -90,72 +90,42 @@ }

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'Props.cpp';
const allImports = new Set([
'#include <react/renderer/core/propsConversions.h>',
'#include <react/renderer/core/PropsParserContext.h>',
]);
const allImports = new Set(['#include <react/renderer/core/propsConversions.h>', '#include <react/renderer/core/PropsParserContext.h>']);
const componentProps = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const componentProps = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
const components = module.components; // No components in this module
return Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})
.map(componentName => {
const component = components[componentName];
const newName = `${componentName}Props`;
if (components == null) {
return null;
}
const propsString = generatePropsString(componentName, component);
const extendString = getClassExtendString(component);
return Object.keys(components).map(componentName => {
const component = components[componentName];
const newName = `${componentName}Props`;
const propsString = generatePropsString(componentName, component);
const extendString = getClassExtendString(component);
const imports = getImports(component.props); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
const imports = getImports(component.props);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
imports.forEach(allImports.add, allImports);
imports.forEach(allImports.add, allImports);
const replacedTemplate = ComponentTemplate({
className: newName,
extendClasses: extendString,
props: propsString
});
return replacedTemplate;
}).join('\n');
}).filter(Boolean).join('\n');
const replacedTemplate = FileTemplate({
componentClasses: componentProps,
libraryName,
imports: Array.from(allImports).sort().join('\n').trim()
});
return new Map([[fileName, replacedTemplate]]);
}
const replacedTemplate = componentTemplate
.replace(/::_CLASSNAME_::/g, newName)
.replace('::_EXTEND_CLASSES_::', extendString)
.replace('::_PROPS_::', propsString);
return replacedTemplate;
})
.join('\n');
})
.filter(Boolean)
.join('\n');
const replacedTemplate = template
.replace(/::_COMPONENT_CLASSES_::/g, componentProps)
.replace('::_LIBRARY_::', libraryName)
.replace(
'::_IMPORTS_::',
Array.from(allImports)
.sort()
.join('\n')
.trim(),
);
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,33 +10,26 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {
convertDefaultTypeToString,
getCppTypeForAnnotation,
getEnumMaskName,
getEnumName,
toSafeCppString,
generateStructName,
getImports,
toIntEnumValueName,
} = require('./CppHelpers.js');
const _require = require('./ComponentsGeneratorUtils.js'),
getNativeTypeFromAnnotation = _require.getNativeTypeFromAnnotation,
getLocalImports = _require.getLocalImports;
const _require2 = require('./CppHelpers.js'),
convertDefaultTypeToString = _require2.convertDefaultTypeToString,
getEnumMaskName = _require2.getEnumMaskName,
getEnumName = _require2.getEnumName,
toSafeCppString = _require2.toSafeCppString,
generateStructName = _require2.generateStructName,
toIntEnumValueName = _require2.toIntEnumValueName; // File path -> contents
// File path -> contents
const template = `
const FileTemplate = ({
imports,
componentClasses
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -47,3 +40,3 @@ * ${'@'}generated by codegen project: GeneratePropsH.js

::_IMPORTS_::
${imports}

@@ -53,3 +46,3 @@ namespace facebook {

::_COMPONENT_CLASSES_::
${componentClasses}

@@ -60,28 +53,39 @@ } // namespace react

const classTemplate = `
::_ENUMS_::
::_STRUCTS_::
class ::_CLASSNAME_:: final::_EXTEND_CLASSES_:: {
const ClassTemplate = ({
enums,
structs,
className,
props,
extendClasses
}) => `
${enums}
${structs}
class JSI_EXPORT ${className} final${extendClasses} {
public:
::_CLASSNAME_::() = default;
::_CLASSNAME_::(const PropsParserContext& context, const ::_CLASSNAME_:: &sourceProps, const RawProps &rawProps);
${className}() = default;
${className}(const PropsParserContext& context, const ${className} &sourceProps, const RawProps &rawProps);
#pragma mark - Props
::_PROPS_::
${props}
};
`.trim();
const enumTemplate = `
enum class ::_ENUM_NAME_:: { ::_VALUES_:: };
const EnumTemplate = ({
enumName,
values,
fromCases,
toCases
}) => `
enum class ${enumName} { ${values} };
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ::_ENUM_NAME_:: &result) {
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ${enumName} &result) {
auto string = (std::string)value;
::_FROM_CASES_::
${fromCases}
abort();
}
static inline std::string toString(const ::_ENUM_NAME_:: &value) {
static inline std::string toString(const ${enumName} &value) {
switch (value) {
::_TO_CASES_::
${toCases}
}

@@ -91,9 +95,14 @@ }

const intEnumTemplate = `
enum class ::_ENUM_NAME_:: { ::_VALUES_:: };
const IntEnumTemplate = ({
enumName,
values,
fromCases,
toCases
}) => `
enum class ${enumName} { ${values} };
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ::_ENUM_NAME_:: &result) {
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ${enumName} &result) {
assert(value.hasType<int>());
auto integerValue = (int)value;
switch (integerValue) {::_FROM_CASES_::
switch (integerValue) {${fromCases}
}

@@ -103,5 +112,5 @@ abort();

static inline std::string toString(const ::_ENUM_NAME_:: &value) {
static inline std::string toString(const ${enumName} &value) {
switch (value) {
::_TO_CASES_::
${toCases}
}

@@ -111,21 +120,27 @@ }

const structTemplate = `struct ::_STRUCT_NAME_:: {
::_FIELDS_::
const StructTemplate = ({
structName,
fields,
fromCases
}) => `struct ${structName} {
${fields}
};
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ::_STRUCT_NAME_:: &result) {
auto map = (better::map<std::string, RawValue>)value;
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ${structName} &result) {
auto map = (butter::map<std::string, RawValue>)value;
::_FROM_CASES_::
${fromCases}
}
static inline std::string toString(const ::_STRUCT_NAME_:: &value) {
return "[Object ::_STRUCT_NAME_::]";
static inline std::string toString(const ${structName} &value) {
return "[Object ${structName}]";
}
`.trim();
const arrayConversionFunction = `static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector<::_STRUCT_NAME_::> &result) {
const ArrayConversionFunctionTemplate = ({
structName
}) => `static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector<${structName}> &result) {
auto items = (std::vector<RawValue>)value;
for (const auto &item : items) {
::_STRUCT_NAME_:: newItem;
${structName} newItem;
fromRawValue(context, item, newItem);

@@ -137,8 +152,10 @@ result.emplace_back(newItem);

const doubleArrayConversionFunction = `static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector<std::vector<::_STRUCT_NAME_::>> &result) {
const DoubleArrayConversionFunctionTemplate = ({
structName
}) => `static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, std::vector<std::vector<${structName}>> &result) {
auto items = (std::vector<std::vector<RawValue>>)value;
for (const std::vector<RawValue> &item : items) {
auto nestedArray = std::vector<::_STRUCT_NAME_::>{};
auto nestedArray = std::vector<${structName}>{};
for (const RawValue &nestedItem : item) {
::_STRUCT_NAME_:: newItem;
${structName} newItem;
fromRawValue(context, nestedItem, newItem);

@@ -152,31 +169,37 @@ nestedArray.emplace_back(newItem);

const arrayEnumTemplate = `
using ::_ENUM_MASK_:: = uint32_t;
const ArrayEnumTemplate = ({
enumName,
enumMask,
values,
fromCases,
toCases
}) => `
using ${enumMask} = uint32_t;
enum class ::_ENUM_NAME_::: ::_ENUM_MASK_:: {
::_VALUES_::
enum class ${enumName}: ${enumMask} {
${values}
};
constexpr bool operator&(
::_ENUM_MASK_:: const lhs,
enum ::_ENUM_NAME_:: const rhs) {
return lhs & static_cast<::_ENUM_MASK_::>(rhs);
${enumMask} const lhs,
enum ${enumName} const rhs) {
return lhs & static_cast<${enumMask}>(rhs);
}
constexpr ::_ENUM_MASK_:: operator|(
::_ENUM_MASK_:: const lhs,
enum ::_ENUM_NAME_:: const rhs) {
return lhs | static_cast<::_ENUM_MASK_::>(rhs);
constexpr ${enumMask} operator|(
${enumMask} const lhs,
enum ${enumName} const rhs) {
return lhs | static_cast<${enumMask}>(rhs);
}
constexpr void operator|=(
::_ENUM_MASK_:: &lhs,
enum ::_ENUM_NAME_:: const rhs) {
lhs = lhs | static_cast<::_ENUM_MASK_::>(rhs);
${enumMask} &lhs,
enum ${enumName} const rhs) {
lhs = lhs | static_cast<${enumMask}>(rhs);
}
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ::_ENUM_MASK_:: &result) {
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, ${enumMask} &result) {
auto items = std::vector<std::string>{value};
for (const auto &item : items) {
::_FROM_CASES_::
${fromCases}
abort();

@@ -186,7 +209,7 @@ }

static inline std::string toString(const ::_ENUM_MASK_:: &value) {
static inline std::string toString(const ${enumMask} &value) {
auto result = std::string{};
auto separator = std::string{", "};
::_TO_CASES_::
${toCases}
if (!result.empty()) {

@@ -199,139 +222,48 @@ result.erase(result.length() - separator.length());

function getClassExtendString(component) {
const extendString =
' : ' +
component.extendsProps
.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'public ViewProps';
default:
(extendProps.knownTypeName );
throw new Error('Invalid knownTypeName');
}
function getClassExtendString(component) {
if (component.extendsProps.length === 0) {
throw new Error('Invalid: component.extendsProps is empty');
}
const extendString = ' : ' + component.extendsProps.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'public ViewProps';
default:
(extendProps.type );
throw new Error('Invalid extended type');
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
})
.join(' ');
default:
extendProps.type;
throw new Error('Invalid extended type');
}
}).join(' ');
return extendString;
}
function getNativeTypeFromAnnotation(
componentName ,
prop,
nameParts ,
) {
const typeAnnotation = prop.typeAnnotation;
switch (typeAnnotation.type) {
case 'BooleanTypeAnnotation':
case 'StringTypeAnnotation':
case 'Int32TypeAnnotation':
case 'DoubleTypeAnnotation':
case 'FloatTypeAnnotation':
return getCppTypeForAnnotation(typeAnnotation.type);
case 'ReservedPropTypeAnnotation':
switch (typeAnnotation.name) {
case 'ColorPrimitive':
return 'SharedColor';
case 'ImageSourcePrimitive':
return 'ImageSource';
case 'PointPrimitive':
return 'Point';
case 'EdgeInsetsPrimitive':
return 'EdgeInsets';
default:
(typeAnnotation.name );
throw new Error('Received unknown ReservedPropTypeAnnotation');
}
case 'ArrayTypeAnnotation': {
const arrayType = typeAnnotation.elementType.type;
if (arrayType === 'ArrayTypeAnnotation') {
return `std::vector<${getNativeTypeFromAnnotation(
componentName,
{typeAnnotation: typeAnnotation.elementType, name: ''},
nameParts.concat([prop.name]),
)}>`;
}
if (arrayType === 'ObjectTypeAnnotation') {
const structName = generateStructName(
componentName,
nameParts.concat([prop.name]),
);
return `std::vector<${structName}>`;
}
if (arrayType === 'StringEnumTypeAnnotation') {
const enumName = getEnumName(componentName, prop.name);
return getEnumMaskName(enumName);
}
const itemAnnotation = getNativeTypeFromAnnotation(
componentName,
{
typeAnnotation: typeAnnotation.elementType,
name: componentName,
},
nameParts.concat([prop.name]),
);
return `std::vector<${itemAnnotation}>`;
}
case 'ObjectTypeAnnotation': {
return generateStructName(componentName, nameParts.concat([prop.name]));
}
case 'StringEnumTypeAnnotation':
return getEnumName(componentName, prop.name);
case 'Int32EnumTypeAnnotation':
return getEnumName(componentName, prop.name);
default:
(typeAnnotation );
throw new Error(
`Received invalid typeAnnotation for ${componentName} prop ${prop.name}, received ${typeAnnotation.type}`,
);
}
}
function convertValueToEnumOption(value ) {
function convertValueToEnumOption(value) {
return toSafeCppString(value);
}
function generateArrayEnumString(
componentName ,
name ,
options ,
) {
function generateArrayEnumString(componentName, name, options) {
const enumName = getEnumName(componentName, name);
const values = options
.map((option, index) => `${toSafeCppString(option)} = 1 << ${index}`)
.join(',\n ');
const fromCases = options
.map(
option =>
`if (item == "${option}") {
const values = options.map((option, index) => `${toSafeCppString(option)} = 1 << ${index}`).join(',\n ');
const fromCases = options.map(option => `if (item == "${option}") {
result |= ${enumName}::${toSafeCppString(option)};
continue;
}`,
)
.join('\n ');
const toCases = options
.map(
option =>
`if (value & ${enumName}::${toSafeCppString(option)}) {
}`).join('\n ');
const toCases = options.map(option => `if (value & ${enumName}::${toSafeCppString(option)}) {
result += "${option}" + separator;
}`,
)
.join('\n' + ' ');
return arrayEnumTemplate
.replace(/::_ENUM_NAME_::/g, enumName)
.replace(/::_ENUM_MASK_::/g, getEnumMaskName(enumName))
.replace('::_VALUES_::', values)
.replace('::_FROM_CASES_::', fromCases)
.replace('::_TO_CASES_::', toCases);
}`).join('\n' + ' ');
return ArrayEnumTemplate({
enumName,
enumMask: getEnumMaskName(enumName),
values,
fromCases,
toCases
});
}

@@ -341,29 +273,14 @@

const typeAnnotation = prop.typeAnnotation;
if (typeAnnotation.type === 'StringEnumTypeAnnotation') {
const values = typeAnnotation.options;
const values = typeAnnotation.options;
const enumName = getEnumName(componentName, prop.name);
const fromCases = values
.map(
value =>
`if (string == "${value}") { result = ${enumName}::${convertValueToEnumOption(
value,
)}; return; }`,
)
.join('\n' + ' ');
const toCases = values
.map(
value =>
`case ${enumName}::${convertValueToEnumOption(
value,
)}: return "${value}";`,
)
.join('\n' + ' ');
return enumTemplate
.replace(/::_ENUM_NAME_::/g, enumName)
.replace('::_VALUES_::', values.map(toSafeCppString).join(', '))
.replace('::_FROM_CASES_::', fromCases)
.replace('::_TO_CASES_::', toCases);
const fromCases = values.map(value => `if (string == "${value}") { result = ${enumName}::${convertValueToEnumOption(value)}; return; }`).join('\n' + ' ');
const toCases = values.map(value => `case ${enumName}::${convertValueToEnumOption(value)}: return "${value}";`).join('\n' + ' ');
return EnumTemplate({
enumName,
values: values.map(toSafeCppString).join(', '),
fromCases: fromCases,
toCases: toCases
});
}

@@ -376,35 +293,18 @@

const typeAnnotation = prop.typeAnnotation;
if (typeAnnotation.type === 'Int32EnumTypeAnnotation') {
const values = typeAnnotation.options;
const values = typeAnnotation.options;
const enumName = getEnumName(componentName, prop.name);
const fromCases = values
.map(
value =>
`
const fromCases = values.map(value => `
case ${value}:
result = ${enumName}::${toIntEnumValueName(prop.name, value)};
return;`,
)
.join('');
const toCases = values
.map(
value =>
`case ${enumName}::${toIntEnumValueName(
prop.name,
value,
)}: return "${value}";`,
)
.join('\n' + ' ');
const valueVariables = values
.map(val => `${toIntEnumValueName(prop.name, val)} = ${val}`)
.join(', ');
return intEnumTemplate
.replace(/::_ENUM_NAME_::/g, enumName)
.replace('::_VALUES_::', valueVariables)
.replace('::_FROM_CASES_::', fromCases)
.replace('::_TO_CASES_::', toCases);
return;`).join('');
const toCases = values.map(value => `case ${enumName}::${toIntEnumValueName(prop.name, value)}: return "${value}";`).join('\n' + ' ');
const valueVariables = values.map(val => `${toIntEnumValueName(prop.name, val)} = ${val}`).join(', ');
return IntEnumTemplate({
enumName,
values: valueVariables,
fromCases,
toCases
});
}

@@ -415,65 +315,42 @@

function generateEnumString(componentName , component) {
return component.props
.map(prop => {
if (
prop.typeAnnotation.type === 'ArrayTypeAnnotation' &&
prop.typeAnnotation.elementType.type === 'StringEnumTypeAnnotation'
) {
return generateArrayEnumString(
componentName,
prop.name,
prop.typeAnnotation.elementType.options,
);
}
function generateEnumString(componentName, component) {
return component.props.map(prop => {
if (prop.typeAnnotation.type === 'ArrayTypeAnnotation' && prop.typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') {
return generateArrayEnumString(componentName, prop.name, prop.typeAnnotation.elementType.options);
}
if (prop.typeAnnotation.type === 'StringEnumTypeAnnotation') {
return generateStringEnum(componentName, prop);
}
if (prop.typeAnnotation.type === 'StringEnumTypeAnnotation') {
return generateStringEnum(componentName, prop);
}
if (prop.typeAnnotation.type === 'Int32EnumTypeAnnotation') {
return generateIntEnum(componentName, prop);
}
if (prop.typeAnnotation.type === 'Int32EnumTypeAnnotation') {
return generateIntEnum(componentName, prop);
}
if (prop.typeAnnotation.type === 'ObjectTypeAnnotation') {
return prop.typeAnnotation.properties
.map(property => {
if (property.typeAnnotation.type === 'StringEnumTypeAnnotation') {
return generateStringEnum(componentName, property);
} else if (
property.typeAnnotation.type === 'Int32EnumTypeAnnotation'
) {
return generateIntEnum(componentName, property);
}
return null;
})
.filter(Boolean)
.join('\n');
}
})
.filter(Boolean)
.join('\n');
if (prop.typeAnnotation.type === 'ObjectTypeAnnotation') {
return prop.typeAnnotation.properties.map(property => {
if (property.typeAnnotation.type === 'StringEnumTypeAnnotation') {
return generateStringEnum(componentName, property);
} else if (property.typeAnnotation.type === 'Int32EnumTypeAnnotation') {
return generateIntEnum(componentName, property);
}
return null;
}).filter(Boolean).join('\n');
}
}).filter(Boolean).join('\n');
}
function generatePropsString(
componentName ,
props ,
) {
return props
.map(prop => {
const nativeType = getNativeTypeFromAnnotation(componentName, prop, []);
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `${nativeType} ${prop.name}{${defaultValue}};`;
})
.join('\n' + ' ');
function generatePropsString(componentName, props) {
return props.map(prop => {
const nativeType = getNativeTypeFromAnnotation(componentName, prop, []);
const defaultValue = convertDefaultTypeToString(componentName, prop);
return `${nativeType} ${prop.name}{${defaultValue}};`;
}).join('\n' + ' ');
}
function getExtendsImports(
extendsProps ,
) {
const imports = new Set();
function getExtendsImports(extendsProps) {
const imports = new Set();
imports.add('#include <react/renderer/core/PropsParserContext.h>');
imports.add('#include <jsi/jsi.h>');
extendsProps.forEach(extendProps => {

@@ -484,109 +361,34 @@ switch (extendProps.type) {

case 'ReactNativeCoreViewProps':
imports.add(
'#include <react/renderer/components/view/ViewProps.h>',
);
imports.add('#include <react/renderer/components/view/ViewProps.h>');
return;
default:
(extendProps.knownTypeName );
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
default:
(extendProps.type );
extendProps.type;
throw new Error('Invalid extended type');
}
});
return imports;
}
function getLocalImports(
properties ,
) {
const imports = new Set();
function addImportsForNativeName(name) {
switch (name) {
case 'ColorPrimitive':
imports.add('#include <react/renderer/graphics/Color.h>');
return;
case 'ImageSourcePrimitive':
imports.add('#include <react/renderer/imagemanager/primitives.h>');
return;
case 'PointPrimitive':
imports.add('#include <react/renderer/graphics/Geometry.h>');
return;
case 'EdgeInsetsPrimitive':
imports.add('#include <react/renderer/graphics/Geometry.h>');
return;
default:
(name );
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);
}
}
properties.forEach(prop => {
const typeAnnotation = prop.typeAnnotation;
if (typeAnnotation.type === 'ReservedPropTypeAnnotation') {
addImportsForNativeName(typeAnnotation.name);
}
if (typeAnnotation.type === 'ArrayTypeAnnotation') {
imports.add('#include <vector>');
if (typeAnnotation.elementType.type === 'StringEnumTypeAnnotation') {
imports.add('#include <cinttypes>');
}
}
if (
typeAnnotation.type === 'ArrayTypeAnnotation' &&
typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation'
) {
addImportsForNativeName(typeAnnotation.elementType.name);
}
if (
typeAnnotation.type === 'ArrayTypeAnnotation' &&
typeAnnotation.elementType.type === 'ObjectTypeAnnotation'
) {
const objectProps = typeAnnotation.elementType.properties;
const objectImports = getImports(objectProps);
const localImports = getLocalImports(objectProps);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
objectImports.forEach(imports.add, imports);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
localImports.forEach(imports.add, imports);
}
if (typeAnnotation.type === 'ObjectTypeAnnotation') {
imports.add('#include <react/renderer/core/propsConversions.h>');
const objectImports = getImports(typeAnnotation.properties);
const localImports = getLocalImports(typeAnnotation.properties);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
objectImports.forEach(imports.add, imports);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
localImports.forEach(imports.add, imports);
}
});
return imports;
}
function generateStructsForComponent(componentName , component) {
function generateStructsForComponent(componentName, component) {
const structs = generateStructs(componentName, component.props, []);
const structArray = Array.from(structs.values());
if (structArray.length < 1) {
return '';
}
return structArray.join('\n\n');
}
function generateStructs(
componentName ,
properties,
nameParts,
) {
const structs = new Map();
function generateStructs(componentName, properties, nameParts) {
const structs = new Map();
properties.forEach(prop => {
const typeAnnotation = prop.typeAnnotation;
if (typeAnnotation.type === 'ObjectTypeAnnotation') {

@@ -596,257 +398,162 @@ // Recursively visit all of the object properties.

const elementProperties = typeAnnotation.properties;
const nestedStructs = generateStructs(
componentName,
elementProperties,
nameParts.concat([prop.name]),
);
nestedStructs.forEach(function(value, key) {
const nestedStructs = generateStructs(componentName, elementProperties, nameParts.concat([prop.name]));
nestedStructs.forEach(function (value, key) {
structs.set(key, value);
});
generateStruct(
structs,
componentName,
nameParts.concat([prop.name]),
typeAnnotation.properties,
);
generateStruct(structs, componentName, nameParts.concat([prop.name]), typeAnnotation.properties);
}
if (
prop.typeAnnotation.type === 'ArrayTypeAnnotation' &&
prop.typeAnnotation.elementType.type === 'ObjectTypeAnnotation'
) {
if (prop.typeAnnotation.type === 'ArrayTypeAnnotation' && prop.typeAnnotation.elementType.type === 'ObjectTypeAnnotation') {
// Recursively visit all of the object properties.
// Note: this is depth first so that the nested structs are ordered first.
const elementProperties = prop.typeAnnotation.elementType.properties;
const nestedStructs = generateStructs(
componentName,
elementProperties,
nameParts.concat([prop.name]),
);
nestedStructs.forEach(function(value, key) {
const nestedStructs = generateStructs(componentName, elementProperties, nameParts.concat([prop.name]));
nestedStructs.forEach(function (value, key) {
structs.set(key, value);
});
}); // Generate this struct and its conversion function.
// Generate this struct and its conversion function.
generateStruct(
structs,
componentName,
nameParts.concat([prop.name]),
elementProperties,
);
generateStruct(structs, componentName, nameParts.concat([prop.name]), elementProperties); // Generate the conversion function for std:vector<Object>.
// Note: This needs to be at the end since it references the struct above.
// Generate the conversion function for std:vector<Object>.
// Note: This needs to be at the end since it references the struct above.
structs.set(
`${[componentName, ...nameParts.concat([prop.name])].join(
'',
)}ArrayStruct`,
arrayConversionFunction.replace(
/::_STRUCT_NAME_::/g,
generateStructName(componentName, nameParts.concat([prop.name])),
),
);
structs.set(`${[componentName, ...nameParts.concat([prop.name])].join('')}ArrayStruct`, ArrayConversionFunctionTemplate({
structName: generateStructName(componentName, nameParts.concat([prop.name]))
}));
}
if (
prop.typeAnnotation.type === 'ArrayTypeAnnotation' &&
prop.typeAnnotation.elementType.type === 'ArrayTypeAnnotation' &&
prop.typeAnnotation.elementType.elementType.type ===
'ObjectTypeAnnotation'
) {
if (prop.typeAnnotation.type === 'ArrayTypeAnnotation' && prop.typeAnnotation.elementType.type === 'ArrayTypeAnnotation' && prop.typeAnnotation.elementType.elementType.type === 'ObjectTypeAnnotation') {
// Recursively visit all of the object properties.
// Note: this is depth first so that the nested structs are ordered first.
const elementProperties =
prop.typeAnnotation.elementType.elementType.properties;
const nestedStructs = generateStructs(
componentName,
elementProperties,
nameParts.concat([prop.name]),
);
nestedStructs.forEach(function(value, key) {
const elementProperties = prop.typeAnnotation.elementType.elementType.properties;
const nestedStructs = generateStructs(componentName, elementProperties, nameParts.concat([prop.name]));
nestedStructs.forEach(function (value, key) {
structs.set(key, value);
});
}); // Generate this struct and its conversion function.
// Generate this struct and its conversion function.
generateStruct(
structs,
componentName,
nameParts.concat([prop.name]),
elementProperties,
);
generateStruct(structs, componentName, nameParts.concat([prop.name]), elementProperties); // Generate the conversion function for std:vector<Object>.
// Note: This needs to be at the end since it references the struct above.
// Generate the conversion function for std:vector<Object>.
// Note: This needs to be at the end since it references the struct above.
structs.set(
`${[componentName, ...nameParts.concat([prop.name])].join(
'',
)}ArrayArrayStruct`,
doubleArrayConversionFunction.replace(
/::_STRUCT_NAME_::/g,
generateStructName(componentName, nameParts.concat([prop.name])),
),
);
structs.set(`${[componentName, ...nameParts.concat([prop.name])].join('')}ArrayArrayStruct`, DoubleArrayConversionFunctionTemplate({
structName: generateStructName(componentName, nameParts.concat([prop.name]))
}));
}
});
return structs;
}
function generateStruct(
structs ,
componentName ,
nameParts ,
properties ,
) {
function generateStruct(structs, componentName, nameParts, properties) {
const structNameParts = nameParts;
const structName = generateStructName(componentName, structNameParts);
const fields = properties.map(property => {
return `${getNativeTypeFromAnnotation(componentName, property, structNameParts)} ${property.name};`;
}).join('\n' + ' ');
properties.forEach(property => {
const name = property.name;
const fields = properties
.map(property => {
return `${getNativeTypeFromAnnotation(
componentName,
property,
structNameParts,
)} ${property.name};`;
})
.join('\n' + ' ');
properties.forEach((property ) => {
const name = property.name;
switch (property.typeAnnotation.type) {
case 'BooleanTypeAnnotation':
return;
case 'StringTypeAnnotation':
return;
case 'Int32TypeAnnotation':
return;
case 'DoubleTypeAnnotation':
return;
case 'FloatTypeAnnotation':
return;
case 'ReservedPropTypeAnnotation':
return;
case 'ArrayTypeAnnotation':
return;
case 'StringEnumTypeAnnotation':
return;
case 'Int32EnumTypeAnnotation':
return;
case 'DoubleTypeAnnotation':
return;
case 'ObjectTypeAnnotation':
const props = property.typeAnnotation.properties;
if (props == null) {
throw new Error(
`Properties are expected for ObjectTypeAnnotation (see ${name} in ${componentName})`,
);
throw new Error(`Properties are expected for ObjectTypeAnnotation (see ${name} in ${componentName})`);
}
generateStruct(structs, componentName, nameParts.concat([name]), props);
return;
default:
(property.typeAnnotation.type );
throw new Error(
`Received invalid component property type ${property.typeAnnotation.type}`,
);
property.typeAnnotation.type;
throw new Error(`Received invalid component property type ${property.typeAnnotation.type}`);
}
});
const fromCases = properties
.map(property => {
const variable = property.name;
return `auto ${variable} = map.find("${property.name}");
const fromCases = properties.map(property => {
const variable = 'tmp_' + property.name;
return `auto ${variable} = map.find("${property.name}");
if (${variable} != map.end()) {
fromRawValue(context, ${variable}->second, result.${variable});
fromRawValue(context, ${variable}->second, result.${property.name});
}`;
})
.join('\n ');
structs.set(
}).join('\n ');
structs.set(structName, StructTemplate({
structName,
structTemplate
.replace(/::_STRUCT_NAME_::/g, structName)
.replace('::_FIELDS_::', fields)
.replace('::_FROM_CASES_::', fromCases),
);
fields,
fromCases
}));
}
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'Props.h';
const allImports = new Set();
const componentClasses = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const allImports = new Set();
if (module.type !== 'Component') {
return;
}
const componentClasses = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const components = module.components; // No components in this module
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
if (components == null) {
return null;
}
return Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('iOS')
);
})
.map(componentName => {
const component = components[componentName];
return Object.keys(components).map(componentName => {
const component = components[componentName];
const newName = `${componentName}Props`;
const structString = generateStructsForComponent(componentName, component);
const enumString = generateEnumString(componentName, component);
const propsString = generatePropsString(componentName, component.props);
const extendString = getClassExtendString(component);
const extendsImports = getExtendsImports(component.extendsProps);
const imports = getLocalImports(component.props); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
const newName = `${componentName}Props`;
const structString = generateStructsForComponent(
componentName,
component,
);
const enumString = generateEnumString(componentName, component);
const propsString = generatePropsString(
componentName,
component.props,
);
const extendString = getClassExtendString(component);
const extendsImports = getExtendsImports(component.extendsProps);
const imports = getLocalImports(component.props);
extendsImports.forEach(allImports.add, allImports); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
extendsImports.forEach(allImports.add, allImports);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
imports.forEach(allImports.add, allImports);
imports.forEach(allImports.add, allImports);
const replacedTemplate = ClassTemplate({
enums: enumString,
structs: structString,
className: newName,
extendClasses: extendString,
props: propsString
});
return replacedTemplate;
}).join('\n\n');
}).filter(Boolean).join('\n\n');
const replacedTemplate = FileTemplate({
componentClasses,
imports: Array.from(allImports).sort().join('\n')
});
return new Map([[fileName, replacedTemplate]]);
}
const replacedTemplate = classTemplate
.replace('::_ENUMS_::', enumString)
.replace('::_STRUCTS_::', structString)
.replace(/::_CLASSNAME_::/g, newName)
.replace('::_EXTEND_CLASSES_::', extendString)
.replace('::_PROPS_::', propsString)
.trim();
return replacedTemplate;
})
.join('\n\n');
})
.filter(Boolean)
.join('\n\n');
const replacedTemplate = template
.replace(/::_COMPONENT_CLASSES_::/g, componentClasses)
.replace(
'::_IMPORTS_::',
Array.from(allImports)
.sort()
.join('\n'),
);
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,27 +10,23 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {
getImports,
toSafeJavaString,
getInterfaceJavaClassName,
getDelegateJavaClassName,
} = require('./JavaHelpers');
const _require = require('./JavaHelpers'),
getImports = _require.getImports,
toSafeJavaString = _require.toSafeJavaString,
getInterfaceJavaClassName = _require.getInterfaceJavaClassName,
getDelegateJavaClassName = _require.getDelegateJavaClassName; // File path -> contents
// File path -> contents
const template = `/**
* Copyright (c) Facebook, Inc. and its affiliates.
const FileTemplate = ({
packageName,
imports,
className,
extendClasses,
interfaceClassName,
methods
}) => `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -40,34 +36,35 @@ * ${'@'}generated by codegen project: GeneratePropsJavaDelegate.js

package ::_PACKAGE_NAME_::;
package ${packageName};
::_IMPORTS_::
${imports}
public class ::_CLASSNAME_::<T extends ::_EXTEND_CLASSES_::, U extends BaseViewManagerInterface<T> & ::_INTERFACE_CLASSNAME_::<T>> extends BaseViewManagerDelegate<T, U> {
public ::_CLASSNAME_::(U viewManager) {
public class ${className}<T extends ${extendClasses}, U extends BaseViewManagerInterface<T> & ${interfaceClassName}<T>> extends BaseViewManagerDelegate<T, U> {
public ${className}(U viewManager) {
super(viewManager);
}
::_METHODS_::
${methods}
}
`;
const propSetterTemplate = `
const PropSetterTemplate = ({
propCases
}) => `
@Override
public void setProperty(T view, String propName, @Nullable Object value) {
::_PROP_CASES_::
${propCases}
}
`;
`.trim();
const commandsTemplate = `
const CommandsTemplate = ({
commandCases
}) => `
@Override
public void receiveCommand(T view, String commandName, ReadableArray args) {
switch (commandName) {
::_COMMAND_CASES_::
${commandCases}
}
}
`;
`.trim();
function getJavaValueForProp(
prop ,
componentName ,
) {
function getJavaValueForProp(prop, componentName) {
const typeAnnotation = prop.typeAnnotation;

@@ -82,10 +79,10 @@

}
case 'StringTypeAnnotation':
const defaultValueString =
typeAnnotation.default === null
? 'null'
: `"${typeAnnotation.default}"`;
const defaultValueString = typeAnnotation.default === null ? 'null' : `"${typeAnnotation.default}"`;
return `value == null ? ${defaultValueString} : (String) value`;
case 'Int32TypeAnnotation':
return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
case 'DoubleTypeAnnotation':

@@ -97,2 +94,3 @@ if (prop.optional) {

}
case 'FloatTypeAnnotation':

@@ -106,2 +104,3 @@ if (typeAnnotation.default === null) {

}
case 'ReservedPropTypeAnnotation':

@@ -111,24 +110,38 @@ switch (typeAnnotation.name) {

return 'ColorPropConverter.getColor(value, view.getContext())';
case 'ImageSourcePrimitive':
return '(ReadableMap) value';
case 'ImageRequestPrimitive':
return '(ReadableMap) value';
case 'PointPrimitive':
return '(ReadableMap) value';
case 'EdgeInsetsPrimitive':
return '(ReadableMap) value';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error('Received unknown ReservedPropTypeAnnotation');
}
case 'ArrayTypeAnnotation': {
return '(ReadableArray) value';
}
case 'ObjectTypeAnnotation': {
return '(ReadableMap) value';
}
case 'ArrayTypeAnnotation':
{
return '(ReadableArray) value';
}
case 'ObjectTypeAnnotation':
{
return '(ReadableMap) value';
}
case 'StringEnumTypeAnnotation':
return '(String) value';
case 'Int32EnumTypeAnnotation':
return `value == null ? ${typeAnnotation.default} : ((Double) value).intValue()`;
default:
(typeAnnotation );
typeAnnotation;
throw new Error('Received invalid typeAnnotation');

@@ -138,6 +151,3 @@ }

function generatePropCasesString(
component ,
componentName ,
) {
function generatePropCasesString(component, componentName) {
if (component.props.length === 0) {

@@ -147,12 +157,7 @@ return 'super.setProperty(view, propName, value);';

const cases = component.props
.map(prop => {
return `case "${prop.name}":
mViewManager.set${toSafeJavaString(
prop.name,
)}(view, ${getJavaValueForProp(prop, componentName)});
const cases = component.props.map(prop => {
return `case "${prop.name}":
mViewManager.set${toSafeJavaString(prop.name)}(view, ${getJavaValueForProp(prop, componentName)});
break;`;
})
.join('\n' + ' ');
}).join('\n' + ' ');
return `switch (propName) {

@@ -166,3 +171,3 @@ ${cases}

function getCommandArgJavaType(param, index) {
const {typeAnnotation} = param;
const typeAnnotation = param.typeAnnotation;

@@ -174,18 +179,25 @@ switch (typeAnnotation.type) {

return `args.getDouble(${index})`;
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return `args.getBoolean(${index})`;
case 'DoubleTypeAnnotation':
return `args.getDouble(${index})`;
case 'FloatTypeAnnotation':
return `(float) args.getDouble(${index})`;
case 'Int32TypeAnnotation':
return `args.getInt(${index})`;
case 'StringTypeAnnotation':
return `args.getString(${index})`;
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error(`Receieved invalid type: ${typeAnnotation.type}`);

@@ -195,15 +207,7 @@ }

function getCommandArguments(
command ,
) {
return [
'view',
...command.typeAnnotation.params.map(getCommandArgJavaType),
].join(', ');
function getCommandArguments(command) {
return ['view', ...command.typeAnnotation.params.map(getCommandArgJavaType)].join(', ');
}
function generateCommandCasesString(
component ,
componentName ,
) {
function generateCommandCasesString(component, componentName) {
if (component.commands.length === 0) {

@@ -213,35 +217,28 @@ return null;

const commandMethods = component.commands
.map(command => {
return `case "${command.name}":
mViewManager.${toSafeJavaString(
command.name,
false,
)}(${getCommandArguments(command)});
const commandMethods = component.commands.map(command => {
return `case "${command.name}":
mViewManager.${toSafeJavaString(command.name, false)}(${getCommandArguments(command)});
break;`;
})
.join('\n' + ' ');
}).join('\n' + ' ');
return commandMethods;
}
function getClassExtendString(component) {
const extendString = component.extendsProps
.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'View';
default:
(extendProps.knownTypeName );
throw new Error('Invalid knownTypeName');
}
default:
(extendProps.type );
throw new Error('Invalid extended type');
}
})
.join('');
function getClassExtendString(component) {
const extendString = component.extendsProps.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'View';
default:
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
default:
extendProps.type;
throw new Error('Invalid extended type');
}
}).join('');
return extendString;

@@ -251,40 +248,32 @@ }

function getDelegateImports(component) {
const imports = getImports(component, 'delegate');
// The delegate needs ReadableArray for commands always.
const imports = getImports(component, 'delegate'); // The delegate needs ReadableArray for commands always.
// The interface doesn't always need it
if (component.commands.length > 0) {
imports.add('import com.facebook.react.bridge.ReadableArray;');
}
imports.add('import androidx.annotation.Nullable;');
imports.add('import com.facebook.react.uimanager.BaseViewManagerDelegate;');
imports.add('import com.facebook.react.uimanager.BaseViewManagerInterface;');
return imports;
}
function generateMethods(propsString, commandsString) {
return [
propSetterTemplate.trim().replace('::_PROP_CASES_::', propsString),
commandsString != null
? commandsTemplate.trim().replace('::_COMMAND_CASES_::', commandsString)
: '',
]
.join('\n\n ')
.trimRight();
function generateMethods(propsString, commandsString) {
return [PropSetterTemplate({
propCases: propsString
}), commandsString != null ? CommandsTemplate({
commandCases: commandsString
}) : ''].join('\n\n ').trimRight();
}
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;
const files = new Map();
Object.keys(schema.modules).forEach(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {

@@ -294,4 +283,4 @@ return;

const {components} = module;
// No components in this module
const components = module.components; // No components in this module
if (components == null) {

@@ -301,46 +290,27 @@ return;

return Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('android')
);
})
.forEach(componentName => {
const component = components[componentName];
const className = getDelegateJavaClassName(componentName);
const interfaceClassName = getInterfaceJavaClassName(componentName);
const imports = getDelegateImports(component);
const propsString = generatePropCasesString(component, componentName);
const commandsString = generateCommandCasesString(
component,
componentName,
);
const extendString = getClassExtendString(component);
const replacedTemplate = template
.replace(
/::_IMPORTS_::/g,
Array.from(imports)
.sort()
.join('\n'),
)
.replace(/::_PACKAGE_NAME_::/g, normalizedPackageName)
.replace(/::_CLASSNAME_::/g, className)
.replace('::_EXTEND_CLASSES_::', extendString)
.replace('::_PROP_CASES_::', propsString)
.replace(
'::_METHODS_::',
generateMethods(propsString, commandsString),
)
.replace(/::_INTERFACE_CLASSNAME_::/g, interfaceClassName);
files.set(`${outputDir}/${className}.java`, replacedTemplate);
return Object.keys(components).filter(componentName => {
const component = components[componentName];
return !(component.excludedPlatforms && component.excludedPlatforms.includes('android'));
}).forEach(componentName => {
const component = components[componentName];
const className = getDelegateJavaClassName(componentName);
const interfaceClassName = getInterfaceJavaClassName(componentName);
const imports = getDelegateImports(component);
const propsString = generatePropCasesString(component, componentName);
const commandsString = generateCommandCasesString(component, componentName);
const extendString = getClassExtendString(component);
const replacedTemplate = FileTemplate({
imports: Array.from(imports).sort().join('\n'),
packageName: normalizedPackageName,
className,
extendClasses: extendString,
methods: generateMethods(propsString, commandsString),
interfaceClassName: interfaceClassName
});
files.set(`${outputDir}/${className}.java`, replacedTemplate);
});
});
return files;
}
return files;
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,26 +10,21 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {
getImports,
toSafeJavaString,
getInterfaceJavaClassName,
} = require('./JavaHelpers');
const _require = require('./JavaHelpers'),
getImports = _require.getImports,
toSafeJavaString = _require.toSafeJavaString,
getInterfaceJavaClassName = _require.getInterfaceJavaClassName; // File path -> contents
// File path -> contents
const template = `/**
* Copyright (c) Facebook, Inc. and its affiliates.
const FileTemplate = ({
packageName,
imports,
className,
extendClasses,
methods
}) => `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -39,8 +34,8 @@ * ${'@'}generated by codegen project: GeneratePropsJavaInterface.js

package ::_PACKAGE_NAME_::;
package ${packageName};
::_IMPORTS_::
${imports}
public interface ::_CLASSNAME_::<T extends ::_EXTEND_CLASSES_::> {
::_METHODS_::
public interface ${className}<T extends ${extendClasses}> {
${methods}
}

@@ -53,6 +48,3 @@ `;

function getJavaValueForProp(
prop ,
imports,
) {
function getJavaValueForProp(prop, imports) {
const typeAnnotation = prop.typeAnnotation;

@@ -68,9 +60,13 @@

}
case 'StringTypeAnnotation':
addNullable(imports);
return '@Nullable String value';
case 'Int32TypeAnnotation':
return 'int value';
case 'DoubleTypeAnnotation':
return 'double value';
case 'FloatTypeAnnotation':

@@ -83,2 +79,3 @@ if (typeAnnotation.default === null) {

}
case 'ReservedPropTypeAnnotation':

@@ -89,31 +86,46 @@ switch (typeAnnotation.name) {

return '@Nullable Integer value';
case 'ImageSourcePrimitive':
addNullable(imports);
return '@Nullable ReadableMap value';
case 'ImageRequestPrimitive':
addNullable(imports);
return '@Nullable ReadableMap value';
case 'PointPrimitive':
addNullable(imports);
return '@Nullable ReadableMap value';
case 'EdgeInsetsPrimitive':
addNullable(imports);
return '@Nullable ReadableMap value';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error('Received unknown ReservedPropTypeAnnotation');
}
case 'ArrayTypeAnnotation': {
addNullable(imports);
return '@Nullable ReadableArray value';
}
case 'ObjectTypeAnnotation': {
addNullable(imports);
return '@Nullable ReadableMap value';
}
case 'ArrayTypeAnnotation':
{
addNullable(imports);
return '@Nullable ReadableArray value';
}
case 'ObjectTypeAnnotation':
{
addNullable(imports);
return '@Nullable ReadableMap value';
}
case 'StringEnumTypeAnnotation':
addNullable(imports);
return '@Nullable String value';
case 'Int32EnumTypeAnnotation':
addNullable(imports);
return '@Nullable Integer value';
default:
(typeAnnotation );
typeAnnotation;
throw new Error('Received invalid typeAnnotation');

@@ -123,3 +135,3 @@ }

function generatePropsString(component , imports) {
function generatePropsString(component, imports) {
if (component.props.length === 0) {

@@ -129,13 +141,9 @@ return '// No props';

return component.props
.map(prop => {
return `void set${toSafeJavaString(
prop.name,
)}(T view, ${getJavaValueForProp(prop, imports)});`;
})
.join('\n' + ' ');
return component.props.map(prop => {
return `void set${toSafeJavaString(prop.name)}(T view, ${getJavaValueForProp(prop, imports)});`;
}).join('\n' + ' ');
}
function getCommandArgJavaType(param) {
const {typeAnnotation} = param;
const typeAnnotation = param.typeAnnotation;

@@ -147,18 +155,25 @@ switch (typeAnnotation.type) {

return 'double';
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Receieved invalid type: ${typeAnnotation.name}`);
}
case 'BooleanTypeAnnotation':
return 'boolean';
case 'DoubleTypeAnnotation':
return 'double';
case 'FloatTypeAnnotation':
return 'float';
case 'Int32TypeAnnotation':
return 'int';
case 'StringTypeAnnotation':
return 'String';
default:
(typeAnnotation.type );
typeAnnotation.type;
throw new Error('Receieved invalid typeAnnotation');

@@ -168,51 +183,34 @@ }

function getCommandArguments(
command ,
componentName ,
) {
return [
'T view',
...command.typeAnnotation.params.map(param => {
const commandArgJavaType = getCommandArgJavaType(param);
function getCommandArguments(command, componentName) {
return ['T view', ...command.typeAnnotation.params.map(param => {
const commandArgJavaType = getCommandArgJavaType(param);
return `${commandArgJavaType} ${param.name}`;
})].join(', ');
}
return `${commandArgJavaType} ${param.name}`;
}),
].join(', ');
function generateCommandsString(component, componentName) {
return component.commands.map(command => {
const safeJavaName = toSafeJavaString(command.name, false);
return `void ${safeJavaName}(${getCommandArguments(command, componentName)});`;
}).join('\n' + ' ');
}
function generateCommandsString(
component ,
componentName ,
) {
return component.commands
.map(command => {
const safeJavaName = toSafeJavaString(command.name, false);
function getClassExtendString(component) {
const extendString = component.extendsProps.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'View';
return `void ${safeJavaName}(${getCommandArguments(
command,
componentName,
)});`;
})
.join('\n' + ' ');
}
default:
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
function getClassExtendString(component) {
const extendString = component.extendsProps
.map(extendProps => {
switch (extendProps.type) {
case 'ReactNativeBuiltInType':
switch (extendProps.knownTypeName) {
case 'ReactNativeCoreViewProps':
return 'View';
default:
(extendProps.knownTypeName );
throw new Error('Invalid knownTypeName');
}
default:
(extendProps.type );
throw new Error('Invalid extended type');
}
})
.join('');
default:
extendProps.type;
throw new Error('Invalid extended type');
}
}).join('');
return extendString;

@@ -222,15 +220,10 @@ }

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
// TODO: This doesn't support custom package name yet.
const normalizedPackageName = 'com.facebook.react.viewmanagers';
const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;
const files = new Map();
Object.keys(schema.modules).forEach(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {

@@ -240,5 +233,4 @@ return;

const {components} = module;
const components = module.components; // No components in this module
// No components in this module
if (components == null) {

@@ -248,44 +240,25 @@ return;

return Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('android')
);
})
.forEach(componentName => {
const component = components[componentName];
const className = getInterfaceJavaClassName(componentName);
const imports = getImports(component, 'interface');
const propsString = generatePropsString(component, imports);
const commandsString = generateCommandsString(
component,
componentName,
);
const extendString = getClassExtendString(component);
const replacedTemplate = template
.replace(
/::_IMPORTS_::/g,
Array.from(imports)
.sort()
.join('\n'),
)
.replace(/::_PACKAGE_NAME_::/g, normalizedPackageName)
.replace(/::_CLASSNAME_::/g, className)
.replace('::_EXTEND_CLASSES_::', extendString)
.replace(
'::_METHODS_::',
[propsString, commandsString].join('\n' + ' ').trimRight(),
)
.replace('::_COMMAND_HANDLERS_::', commandsString);
files.set(`${outputDir}/${className}.java`, replacedTemplate);
return Object.keys(components).filter(componentName => {
const component = components[componentName];
return !(component.excludedPlatforms && component.excludedPlatforms.includes('android'));
}).forEach(componentName => {
const component = components[componentName];
const className = getInterfaceJavaClassName(componentName);
const imports = getImports(component, 'interface');
const propsString = generatePropsString(component, imports);
const commandsString = generateCommandsString(component, componentName);
const extendString = getClassExtendString(component);
const replacedTemplate = FileTemplate({
imports: Array.from(imports).sort().join('\n'),
packageName: normalizedPackageName,
className,
extendClasses: extendString,
methods: [propsString, commandsString].join('\n' + ' ').trimRight()
});
files.set(`${outputDir}/${className}.java`, replacedTemplate);
});
});
return files;
}
return files;
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,24 +10,19 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const PojoCollector = require('./PojoCollector');
const {capitalize} = require('../../Utils');
const {serializePojo} = require('./serializePojo');
const _require = require('../../Utils'),
capitalize = _require.capitalize;
const _require2 = require('./serializePojo'),
serializePojo = _require2.serializePojo;
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
) {
generate(libraryName, schema, packageName) {
const pojoCollector = new PojoCollector();
const basePackageName = 'com.facebook.react.viewmanagers';
Object.keys(schema.modules).forEach(hasteModuleName => {
const module = schema.modules[hasteModuleName];
if (module.type !== 'Component') {

@@ -37,4 +32,4 @@ return;

const {components} = module;
// No components in this module
const components = module.components; // No components in this module
if (components == null) {

@@ -44,40 +39,25 @@ return null;

Object.keys(components)
.filter(componentName => {
const component = components[componentName];
return !(
component.excludedPlatforms &&
component.excludedPlatforms.includes('android')
);
})
.forEach(componentName => {
const component = components[componentName];
if (component == null) {
return;
}
Object.keys(components).filter(componentName => {
const component = components[componentName];
return !(component.excludedPlatforms && component.excludedPlatforms.includes('android'));
}).forEach(componentName => {
const component = components[componentName];
const {props} = component;
if (component == null) {
return;
}
pojoCollector.process(
capitalize(hasteModuleName),
`${capitalize(componentName)}Props`,
{
type: 'ObjectTypeAnnotation',
properties: props,
},
);
const props = component.props;
pojoCollector.process(capitalize(hasteModuleName), `${capitalize(componentName)}Props`, {
type: 'ObjectTypeAnnotation',
properties: props
});
});
});
const pojoDir = basePackageName.split('.').join('/');
return new Map(pojoCollector.getAllPojos().map(pojo => {
return [`java/${pojoDir}/${pojo.namespace}/${pojo.name}.java`, serializePojo(pojo, basePackageName)];
}));
}
return new Map(
pojoCollector.getAllPojos().map(pojo => {
return [
`java/${pojoDir}/${pojo.namespace}/${pojo.name}.java`,
serializePojo(pojo, basePackageName),
];
}),
);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,144 +10,76 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
const {capitalize} = require('../../Utils');
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const _require = require('../../Utils'),
capitalize = _require.capitalize;
class PojoCollector {
constructor() {
_defineProperty(this, "_pojos", new Map());
}
class PojoCollector {
_pojos = new Map();
process(
namespace ,
pojoName ,
typeAnnotation ,
) {
process(namespace, pojoName, typeAnnotation) {
switch (typeAnnotation.type) {
case 'ObjectTypeAnnotation': {
this._insertPojo(namespace, pojoName, typeAnnotation);
return {
type: 'PojoTypeAliasTypeAnnotation',
name: pojoName,
};
}
case 'ArrayTypeAnnotation': {
const arrayTypeAnnotation = typeAnnotation;
// TODO: Flow assumes elementType can be any. Fix this.
const elementType
= arrayTypeAnnotation.elementType;
case 'ObjectTypeAnnotation':
{
this._insertPojo(namespace, pojoName, typeAnnotation);
const pojoElementType = (() => {
switch (elementType.type) {
case 'ObjectTypeAnnotation': {
this._insertPojo(namespace, `${pojoName}Element`, elementType);
return {
type: 'PojoTypeAliasTypeAnnotation',
name: `${pojoName}Element`,
};
return {
type: 'PojoTypeAliasTypeAnnotation',
name: pojoName
};
}
case 'ArrayTypeAnnotation':
{
const arrayTypeAnnotation = typeAnnotation; // TODO: Flow assumes elementType can be any. Fix this.
const elementType = arrayTypeAnnotation.elementType;
const pojoElementType = (() => {
switch (elementType.type) {
case 'ObjectTypeAnnotation':
{
this._insertPojo(namespace, `${pojoName}Element`, elementType);
return {
type: 'PojoTypeAliasTypeAnnotation',
name: `${pojoName}Element`
};
}
case 'ArrayTypeAnnotation':
{
const objectTypeAnnotation = elementType.elementType;
this._insertPojo(namespace, `${pojoName}ElementElement`, objectTypeAnnotation);
return {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'PojoTypeAliasTypeAnnotation',
name: `${pojoName}ElementElement`
}
};
}
default:
{
return elementType;
}
}
case 'ArrayTypeAnnotation': {
const {elementType: objectTypeAnnotation} = elementType;
this._insertPojo(
namespace,
`${pojoName}ElementElement`,
objectTypeAnnotation,
);
return {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'PojoTypeAliasTypeAnnotation',
name: `${pojoName}ElementElement`,
},
};
}
default: {
return elementType;
}
}
})();
})();
return {
type: 'ArrayTypeAnnotation',
elementType: pojoElementType,
};
}
return {
type: 'ArrayTypeAnnotation',
elementType: pojoElementType
};
}
default:

@@ -158,18 +90,8 @@ return typeAnnotation;

_insertPojo(
namespace ,
pojoName ,
objectTypeAnnotation ,
) {
_insertPojo(namespace, pojoName, objectTypeAnnotation) {
const properties = objectTypeAnnotation.properties.map(property => {
const propertyPojoName = pojoName + capitalize(property.name);
return {
...property,
typeAnnotation: this.process(
namespace,
propertyPojoName,
property.typeAnnotation,
),
};
return _objectSpread({}, property, {
typeAnnotation: this.process(namespace, propertyPojoName, property.typeAnnotation)
});
});

@@ -180,11 +102,12 @@

namespace,
properties,
properties
});
}
getAllPojos() {
getAllPojos() {
return [...this._pojos.values()];
}
}
module.exports = PojoCollector;
module.exports = PojoCollector;
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,18 +10,14 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {capitalize} = require('../../Utils');
const _require = require('../../Utils'),
capitalize = _require.capitalize;
function toJavaType(typeAnnotation, addImport) {
const importNullable = () => addImport('androidx.annotation.Nullable');
function toJavaType(
typeAnnotation ,
addImport ,
) {
const importNullable = () => addImport('androidx.annotation.Nullable');
const importReadableMap = () =>
addImport('com.facebook.react.bridge.ReadableMap');
const importReadableMap = () => addImport('com.facebook.react.bridge.ReadableMap');
const importArrayList = () => addImport('java.util.ArrayList');
switch (typeAnnotation.type) {

@@ -31,29 +27,38 @@ /**

*/
case 'BooleanTypeAnnotation': {
if (typeAnnotation.default === null) {
importNullable();
return '@Nullable Boolean';
} else {
return 'boolean';
case 'BooleanTypeAnnotation':
{
if (typeAnnotation.default === null) {
importNullable();
return '@Nullable Boolean';
} else {
return 'boolean';
}
}
}
case 'StringTypeAnnotation': {
importNullable();
return '@Nullable String';
}
case 'DoubleTypeAnnotation': {
return 'double';
}
case 'FloatTypeAnnotation': {
if (typeAnnotation.default === null) {
case 'StringTypeAnnotation':
{
importNullable();
return '@Nullable Float';
} else {
return 'float';
return '@Nullable String';
}
}
case 'Int32TypeAnnotation': {
return 'int';
}
case 'DoubleTypeAnnotation':
{
return 'double';
}
case 'FloatTypeAnnotation':
{
if (typeAnnotation.default === null) {
importNullable();
return '@Nullable Float';
} else {
return 'float';
}
}
case 'Int32TypeAnnotation':
{
return 'int';
}
/**

@@ -63,2 +68,3 @@ * Enums

// TODO: Make StringEnumTypeAnnotation type-safe?
case 'StringEnumTypeAnnotation':

@@ -68,2 +74,3 @@ importNullable();

// TODO: Make Int32EnumTypeAnnotation type-safe?
case 'Int32EnumTypeAnnotation':

@@ -76,32 +83,39 @@ importNullable();

*/
case 'ReservedPropTypeAnnotation': {
switch (typeAnnotation.name) {
case 'ColorPrimitive':
importNullable();
return '@Nullable Integer';
// TODO: Make ImageSourcePrimitive type-safe
case 'ImageSourcePrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
case 'ReservedPropTypeAnnotation':
{
switch (typeAnnotation.name) {
case 'ColorPrimitive':
importNullable();
return '@Nullable Integer';
// TODO: Make ImageSourcePrimitive type-safe
// TODO: Make PointPrimitive type-safe
case 'PointPrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
case 'ImageSourcePrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
// TODO: Make ImageRequestPrimitive type-safe
// TODO: Make EdgeInsetsPrimitive type-safe
case 'EdgeInsetsPrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
default:
(typeAnnotation.name );
throw new Error(
`Received unknown ReservedPropTypeAnnotation ${typeAnnotation.name}`,
);
case 'ImageRequestPrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
// TODO: Make PointPrimitive type-safe
case 'PointPrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
// TODO: Make EdgeInsetsPrimitive type-safe
case 'EdgeInsetsPrimitive':
importNullable();
importReadableMap();
return '@Nullable ReadableMap';
default:
typeAnnotation.name;
throw new Error(`Received unknown ReservedPropTypeAnnotation ${typeAnnotation.name}`);
}
}
}

@@ -111,115 +125,134 @@ /**

*/
case 'PojoTypeAliasTypeAnnotation': {
return typeAnnotation.name;
}
case 'PojoTypeAliasTypeAnnotation':
{
return typeAnnotation.name;
}
/**
* Arrays
*/
case 'ArrayTypeAnnotation': {
const {elementType} = typeAnnotation;
const elementTypeString = (() => {
switch (elementType.type) {
/**
* Primitives
*/
case 'BooleanTypeAnnotation': {
return 'Boolean';
}
case 'StringTypeAnnotation': {
return 'String';
}
case 'DoubleTypeAnnotation': {
return 'Double';
}
case 'FloatTypeAnnotation': {
return 'Float';
}
case 'Int32TypeAnnotation': {
return 'Integer';
}
case 'ArrayTypeAnnotation':
{
const elementType = typeAnnotation.elementType;
/**
* Enums
*/
// TODO: Make StringEnums type-safe in Pojos
case 'StringEnumTypeAnnotation': {
return 'String';
}
const elementTypeString = (() => {
switch (elementType.type) {
/**
* Primitives
*/
case 'BooleanTypeAnnotation':
{
return 'Boolean';
}
/**
* Other Pojo objects
*/
case 'PojoTypeAliasTypeAnnotation': {
return elementType.name;
}
case 'StringTypeAnnotation':
{
return 'String';
}
/**
* Reserved types
*/
case 'ReservedPropTypeAnnotation': {
switch (elementType.name) {
case 'ColorPrimitive':
case 'DoubleTypeAnnotation':
{
return 'Double';
}
case 'FloatTypeAnnotation':
{
return 'Float';
}
case 'Int32TypeAnnotation':
{
return 'Integer';
}
// TODO: Make ImageSourcePrimitive type-safe
case 'ImageSourcePrimitive':
importReadableMap();
return 'ReadableMap';
/**
* Enums
*/
// TODO: Make StringEnums type-safe in Pojos
// TODO: Make PointPrimitive type-safe
case 'PointPrimitive':
importReadableMap();
return 'ReadableMap';
case 'StringEnumTypeAnnotation':
{
return 'String';
}
// TODO: Make EdgeInsetsPrimitive type-safe
case 'EdgeInsetsPrimitive':
importReadableMap();
return 'ReadableMap';
default:
(elementType.name );
throw new Error(
`Received unknown ReservedPropTypeAnnotation ${elementType.name}`,
);
}
}
/**
* Other Pojo objects
*/
// Arrays
case 'ArrayTypeAnnotation': {
const {elementType: pojoTypeAliasTypeAnnotation} = elementType;
case 'PojoTypeAliasTypeAnnotation':
{
return elementType.name;
}
importArrayList();
return `ArrayList<${pojoTypeAliasTypeAnnotation.name}>`;
/**
* Reserved types
*/
case 'ReservedPropTypeAnnotation':
{
switch (elementType.name) {
case 'ColorPrimitive':
return 'Integer';
// TODO: Make ImageSourcePrimitive type-safe
case 'ImageSourcePrimitive':
importReadableMap();
return 'ReadableMap';
// TODO: Make ImageRequestPrimitive type-safe
case 'ImageRequestPrimitive':
importReadableMap();
return 'ReadableMap';
// TODO: Make PointPrimitive type-safe
case 'PointPrimitive':
importReadableMap();
return 'ReadableMap';
// TODO: Make EdgeInsetsPrimitive type-safe
case 'EdgeInsetsPrimitive':
importReadableMap();
return 'ReadableMap';
default:
elementType.name;
throw new Error(`Received unknown ReservedPropTypeAnnotation ${elementType.name}`);
}
}
// Arrays
case 'ArrayTypeAnnotation':
{
const pojoTypeAliasTypeAnnotation = elementType.elementType;
importArrayList();
return `ArrayList<${pojoTypeAliasTypeAnnotation.name}>`;
}
default:
{
elementType.type;
throw new Error(`Unrecognized PojoTypeAnnotation Array element type annotation '${typeAnnotation.type}'`);
}
}
default: {
(elementType.type );
throw new Error(
`Unrecognized PojoTypeAnnotation Array element type annotation '${typeAnnotation.type}'`,
);
}
}
})();
})();
importArrayList();
return `ArrayList<${elementTypeString}>`;
}
importArrayList();
return `ArrayList<${elementTypeString}>`;
}
default: {
(typeAnnotation.type );
throw new Error(
`Unrecognized PojoTypeAnnotation '${typeAnnotation.type}'`,
);
}
default:
{
typeAnnotation.type;
throw new Error(`Unrecognized PojoTypeAnnotation '${typeAnnotation.type}'`);
}
}
}
function toJavaMemberName(property ) {
function toJavaMemberName(property) {
return `m${capitalize(property.name)}`;
}
function toJavaMemberDeclaration(
property ,
addImport ,
) {
function toJavaMemberDeclaration(property, addImport) {
const type = toJavaType(property.typeAnnotation, addImport);

@@ -230,7 +263,6 @@ const memberName = toJavaMemberName(property);

function toJavaGetter(property , addImport ) {
function toJavaGetter(property, addImport) {
const type = toJavaType(property.typeAnnotation, addImport);
const getterName = `get${capitalize(property.name)}`;
const memberName = toJavaMemberName(property);
addImport('com.facebook.proguard.annotations.DoNotStrip');

@@ -243,5 +275,6 @@ return `@DoNotStrip

function serializePojo(pojo , basePackageName ) {
const importSet = new Set();
const addImport = ($import ) => {
function serializePojo(pojo, basePackageName) {
const importSet = new Set();
const addImport = $import => {
importSet.add($import);

@@ -251,27 +284,8 @@ };

addImport('com.facebook.proguard.annotations.DoNotStrip');
const indent = ' '.repeat(2);
const members = pojo.properties
.map(property => toJavaMemberDeclaration(property, addImport))
.map(member => `${indent}${member}`)
.join('\n');
const getters = pojo.properties
.map(property => toJavaGetter(property, addImport))
.map(getter =>
getter
.split('\n')
.map(line => `${indent}${line}`)
.join('\n'),
)
.join('\n');
const imports = [...importSet]
.map($import => `import ${$import};`)
.sort()
.join('\n');
const members = pojo.properties.map(property => toJavaMemberDeclaration(property, addImport)).map(member => `${indent}${member}`).join('\n');
const getters = pojo.properties.map(property => toJavaGetter(property, addImport)).map(getter => getter.split('\n').map(line => `${indent}${line}`).join('\n')).join('\n');
const imports = [...importSet].map($import => `import ${$import};`).sort().join('\n');
return `/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -294,2 +308,4 @@ * This source code is licensed under the MIT license found in the

module.exports = {serializePojo};
module.exports = {
serializePojo
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,16 +10,13 @@ * This source code is licensed under the MIT license found in the

*/
'use strict'; // File path -> contents
'use strict';
// File path -> contents
const template = `
const FileTemplate = ({
libraryName,
componentNames
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -29,3 +26,3 @@ * ${'@'}generated by codegen project: GenerateShadowNodeCpp.js

#include <react/renderer/components/::_LIBRARY_::/ShadowNodes.h>
#include <react/renderer/components/${libraryName}/ShadowNodes.h>

@@ -35,3 +32,3 @@ namespace facebook {

::_COMPONENT_NAMES_::
${componentNames}

@@ -42,51 +39,42 @@ } // namespace react

const componentTemplate = `
extern const char ::_CLASSNAME_::ComponentName[] = "::_CLASSNAME_::";
const ComponentTemplate = ({
className
}) => `
extern const char ${className}ComponentName[] = "${className}";
`.trim();
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'ShadowNodes.cpp';
const componentNames = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const componentNames = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
const components = module.components; // No components in this module
return Object.keys(components)
.map(componentName => {
if (components[componentName].interfaceOnly === true) {
return;
}
const replacedTemplate = componentTemplate.replace(
/::_CLASSNAME_::/g,
componentName,
);
if (components == null) {
return null;
}
return replacedTemplate;
})
.join('\n');
})
.filter(Boolean)
.join('\n');
return Object.keys(components).map(componentName => {
if (components[componentName].interfaceOnly === true) {
return;
}
const replacedTemplate = template
.replace(/::_COMPONENT_NAMES_::/g, componentNames)
.replace('::_LIBRARY_::', libraryName);
const replacedTemplate = ComponentTemplate({
className: componentName
});
return replacedTemplate;
}).join('\n');
}).filter(Boolean).join('\n');
const replacedTemplate = FileTemplate({
componentNames,
libraryName
});
return new Map([[fileName, replacedTemplate]]);
}
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,16 +10,14 @@ * This source code is licensed under the MIT license found in the

*/
'use strict'; // File path -> contents
'use strict';
// File path -> contents
const template = `
const FileTemplate = ({
imports,
libraryName,
componentClasses
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -31,4 +29,6 @@ * ${'@'}generated by codegen project: GenerateShadowNodeH.js

::_IMPORTS_::#include <react/renderer/components/::_LIBRARY_::/Props.h>
${imports}#include <react/renderer/components/${libraryName}/Props.h>
#include <react/renderer/components/${libraryName}/States.h>
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
#include <jsi/jsi.h>

@@ -38,3 +38,3 @@ namespace facebook {

::_COMPONENT_CLASSES_::
${componentClasses}

@@ -45,74 +45,57 @@ } // namespace react

const componentTemplate = `
extern const char ::_CLASSNAME_::ComponentName[];
const ComponentTemplate = ({
className,
eventEmitter
}) => `
JSI_EXPORT extern const char ${className}ComponentName[];
/*
* \`ShadowNode\` for <::_CLASSNAME_::> component.
* \`ShadowNode\` for <${className}> component.
*/
using ::_CLASSNAME_::ShadowNode = ConcreteViewShadowNode<
::_CLASSNAME_::ComponentName,
::_CLASSNAME_::Props::_EVENT_EMITTER_::>;
using ${className}ShadowNode = ConcreteViewShadowNode<
${className}ComponentName,
${className}Props${eventEmitter},
${className}State>;
`.trim();
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'ShadowNodes.h';
const moduleResults = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
let hasAnyEvents = false;
if (module.type !== 'Component') {
return;
}
const moduleResults = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
const components = module.components; // No components in this module
const {components} = module;
// No components in this module
if (components == null) {
return null;
}
if (components == null) {
return null;
}
return Object.keys(components)
.map(componentName => {
const component = components[componentName];
if (component.interfaceOnly === true) {
return;
}
return Object.keys(components).map(componentName => {
const component = components[componentName];
const hasEvents = component.events.length > 0;
if (component.interfaceOnly === true) {
return;
}
if (hasEvents) {
hasAnyEvents = true;
}
const eventEmitter = hasEvents
? `,\n${componentName}EventEmitter`
: '';
const replacedTemplate = componentTemplate
.replace(/::_CLASSNAME_::/g, componentName)
.replace('::_EVENT_EMITTER_::', eventEmitter);
return replacedTemplate;
})
.join('\n\n');
})
.filter(Boolean)
.join('\n\n');
const eventEmitter = `,\n ${componentName}EventEmitter`;
const replacedTemplate = ComponentTemplate({
className: componentName,
eventEmitter
});
return replacedTemplate;
}).join('\n\n');
}).filter(Boolean).join('\n\n');
const eventEmitterImport = `#include <react/renderer/components/${libraryName}/EventEmitters.h>\n`;
const replacedTemplate = FileTemplate({
componentClasses: moduleResults,
libraryName,
imports: eventEmitterImport
});
return new Map([[fileName, replacedTemplate]]);
}
const replacedTemplate = template
.replace(/::_COMPONENT_CLASSES_::/g, moduleResults)
.replace('::_LIBRARY_::', libraryName)
.replace('::_IMPORTS_::', hasAnyEvents ? eventEmitterImport : '');
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,24 +10,18 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {getImports, toSafeCppString} = require('./CppHelpers');
const _require = require('./CppHelpers'),
getImports = _require.getImports,
toSafeCppString = _require.toSafeCppString;
const fileTemplate = `
const FileTemplate = ({
libraryName,
imports,
componentTests
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -39,15 +33,20 @@ * ${'@'}generated by codegen project: GenerateTests.js

#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/components/::_LIBRARY_NAME_::/Props.h>
::_IMPORTS_::
#include <react/renderer/components/${libraryName}/Props.h>
${imports}
using namespace facebook::react;
::_COMPONENT_TESTS_::
`;
${componentTests}
`.trim();
const testTemplate = `
TEST(::_COMPONENT_NAME_::_::_TEST_NAME_::, etc) {
const TestTemplate = ({
componentName,
testName,
propName,
propValue
}) => `
TEST(${componentName}_${testName}, etc) {
auto propParser = RawPropsParser();
propParser.prepare<::_COMPONENT_NAME_::>();
auto const &sourceProps = ::_COMPONENT_NAME_::();
auto const &rawProps = RawProps(folly::dynamic::object("::_PROP_NAME_::", ::_PROP_VALUE_::));
propParser.prepare<${componentName}>();
auto const &sourceProps = ${componentName}();
auto const &rawProps = RawProps(folly::dynamic::object("${propName}", ${propValue}));

@@ -58,3 +57,3 @@ ContextContainer contextContainer{};

rawProps.parse(propParser, parserContext);
::_COMPONENT_NAME_::(parserContext, sourceProps, rawProps);
${componentName}(parserContext, sourceProps, rawProps);
}

@@ -65,17 +64,13 @@ `;

const cases = [];
if (typeAnnotation.type === 'StringEnumTypeAnnotation') {
typeAnnotation.options.forEach(option =>
cases.push({
propName,
testName: `${propName}_${toSafeCppString(option)}`,
propValue: option,
}),
);
typeAnnotation.options.forEach(option => cases.push({
propName,
testName: `${propName}_${toSafeCppString(option)}`,
propValue: option
}));
} else if (typeAnnotation.type === 'StringTypeAnnotation') {
cases.push({
propName,
propValue:
typeAnnotation.default != null && typeAnnotation.default !== ''
? typeAnnotation.default
: 'foo',
propValue: typeAnnotation.default != null && typeAnnotation.default !== '' ? typeAnnotation.default : 'foo'
});

@@ -85,9 +80,8 @@ } else if (typeAnnotation.type === 'BooleanTypeAnnotation') {

propName: propName,
propValue: typeAnnotation.default != null ? typeAnnotation.default : true,
});
// $FlowFixMe[incompatible-type]
propValue: typeAnnotation.default != null ? typeAnnotation.default : true
}); // $FlowFixMe[incompatible-type]
} else if (typeAnnotation.type === 'IntegerTypeAnnotation') {
cases.push({
propName,
propValue: typeAnnotation.default || 10,
propValue: typeAnnotation.default || 10
});

@@ -97,3 +91,3 @@ } else if (typeAnnotation.type === 'FloatTypeAnnotation') {

propName,
propValue: typeAnnotation.default != null ? typeAnnotation.default : 0.1,
propValue: typeAnnotation.default != null ? typeAnnotation.default : 0.1
});

@@ -104,3 +98,3 @@ } else if (typeAnnotation.type === 'ReservedPropTypeAnnotation') {

propName,
propValue: 1,
propValue: 1
});

@@ -111,3 +105,3 @@ } else if (typeAnnotation.name === 'PointPrimitive') {

propValue: 'folly::dynamic::object("x", 1)("y", 1)',
raw: true,
raw: true
});

@@ -118,3 +112,3 @@ } else if (typeAnnotation.name === 'ImageSourcePrimitive') {

propValue: 'folly::dynamic::object("url", "testurl")',
raw: true,
raw: true
});

@@ -128,11 +122,15 @@ }

function generateTestsString(name, component) {
function createTest({testName, propName, propValue, raw = false} ) {
const value =
!raw && typeof propValue === 'string' ? `"${propValue}"` : propValue;
return testTemplate
.replace(/::_COMPONENT_NAME_::/g, name)
.replace(/::_TEST_NAME_::/g, testName != null ? testName : propName)
.replace(/::_PROP_NAME_::/g, propName)
.replace(/::_PROP_VALUE_::/g, String(value));
function createTest({
testName,
propName,
propValue,
raw = false
}) {
const value = !raw && typeof propValue === 'string' ? `"${propValue}"` : propValue;
return TestTemplate({
componentName: name,
testName: testName != null ? testName : propName,
propName,
propValue: String(value)
});
}

@@ -143,9 +141,7 @@

}, []);
const baseTest = {
testName: 'DoesNotDie',
propName: 'xx_invalid_xx',
propValue: 'xx_invalid_xx',
propValue: 'xx_invalid_xx'
};
return [baseTest, ...testCases].map(createTest).join('');

@@ -155,56 +151,36 @@ }

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const fileName = 'Tests.cpp';
const allImports = new Set([
'#include <react/renderer/core/propsConversions.h>',
'#include <react/renderer/core/RawProps.h>',
'#include <react/renderer/core/RawPropsParser.h>',
]);
const allImports = new Set(['#include <react/renderer/core/propsConversions.h>', '#include <react/renderer/core/RawProps.h>', '#include <react/renderer/core/RawPropsParser.h>']);
const componentTests = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const componentTests = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
if (components == null) {
return null;
}
const components = module.components;
return Object.keys(components)
.map(componentName => {
const component = components[componentName];
const name = `${componentName}Props`;
if (components == null) {
return null;
}
const imports = getImports(component.props);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
imports.forEach(allImports.add, allImports);
return Object.keys(components).map(componentName => {
const component = components[componentName];
const name = `${componentName}Props`;
const imports = getImports(component.props); // $FlowFixMe[method-unbinding] added when improving typing for this parameters
return generateTestsString(name, component);
})
.join('');
})
.filter(Boolean)
.join('');
imports.forEach(allImports.add, allImports);
return generateTestsString(name, component);
}).join('');
}).filter(Boolean).join('');
const imports = Array.from(allImports).sort().join('\n').trim();
const replacedTemplate = FileTemplate({
imports,
libraryName,
componentTests
});
return new Map([[fileName, replacedTemplate]]);
}
const imports = Array.from(allImports)
.sort()
.join('\n')
.trim();
const replacedTemplate = fileTemplate
.replace(/::_IMPORTS_::/g, imports)
.replace(/::_LIBRARY_NAME_::/g, libraryName)
.replace(/::_COMPONENT_TESTS_::/g, componentTests)
.trim();
return new Map([[fileName, replacedTemplate]]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,18 +10,16 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const j = require('jscodeshift');
const j = require('jscodeshift'); // File path -> contents
// File path -> contents
const template = `
const FileTemplate = ({
imports,
componentConfig
}) => `
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -35,9 +33,9 @@ * @flow

::_IMPORTS_::
${imports}
::_COMPONENT_CONFIG_::
`;
${componentConfig}
`; // We use this to add to a set. Need to make sure we aren't importing
// this multiple times.
// We use this to add to a set. Need to make sure we aren't importing
// this multiple times.
const UIMANAGER_IMPORT = 'const {UIManager} = require("react-native")';

@@ -56,19 +54,25 @@

return j.literal(true);
case 'ReservedPropTypeAnnotation':
switch (typeAnnotation.name) {
case 'ColorPrimitive':
return j.template.expression`{ process: require('processColor') }`;
return j.template.expression`{ process: require('react-native/Libraries/StyleSheet/processColor') }`;
case 'ImageSourcePrimitive':
return j.template
.expression`{ process: require('resolveAssetSource') }`;
return j.template.expression`{ process: require('react-native/Libraries/Image/resolveAssetSource') }`;
case 'ImageRequestPrimitive':
throw new Error('ImageRequest should not be used in props');
case 'PointPrimitive':
return j.template.expression`{ diff: require('pointsDiffer') }`;
return j.template.expression`{ diff: require('react-native/Libraries/Utilities/differ/pointsDiffer') }`;
case 'EdgeInsetsPrimitive':
return j.template.expression`{ diff: require('insetsDiffer') }`;
return j.template.expression`{ diff: require('react-native/Libraries/Utilities/differ/insetsDiffer') }`;
default:
(typeAnnotation.name );
throw new Error(
`Received unknown native typeAnnotation: "${typeAnnotation.name}"`,
);
typeAnnotation.name;
throw new Error(`Received unknown native typeAnnotation: "${typeAnnotation.name}"`);
}
case 'ArrayTypeAnnotation':

@@ -78,40 +82,61 @@ if (typeAnnotation.elementType.type === 'ReservedPropTypeAnnotation') {

case 'ColorPrimitive':
return j.template
.expression`{ process: require('processColorArray') }`;
return j.template.expression`{ process: require('react-native/Libraries/StyleSheet/processColorArray') }`;
case 'ImageSourcePrimitive':
return j.literal(true);
case 'PointPrimitive':
return j.literal(true);
default:
throw new Error(
`Received unknown array native typeAnnotation: "${typeAnnotation.elementType.name}"`,
);
throw new Error(`Received unknown array native typeAnnotation: "${typeAnnotation.elementType.name}"`);
}
}
return j.literal(true);
default:
(typeAnnotation );
throw new Error(
`Received unknown typeAnnotation: "${typeAnnotation.type}"`,
);
typeAnnotation;
throw new Error(`Received unknown typeAnnotation: "${typeAnnotation.type}"`);
}
}
const componentTemplate = `
let nativeComponentName = '::_COMPONENT_NAME_WITH_COMPAT_SUPPORT_::';
::_DEPRECATION_CHECK_::
export default NativeComponentRegistry.get(nativeComponentName, () => VIEW_CONFIG);
const ComponentTemplate = ({
componentName,
paperComponentName,
paperComponentNameDeprecated
}) => {
var _paperComponentName;
const nativeComponentName = (_paperComponentName = paperComponentName) !== null && _paperComponentName !== void 0 ? _paperComponentName : componentName;
return `
let nativeComponentName = '${nativeComponentName}';
${paperComponentNameDeprecated != null ? DeprecatedComponentNameCheckTemplate({
componentName,
paperComponentNameDeprecated
}) : ''}
export const __INTERNAL_VIEW_CONFIG = VIEW_CONFIG;
export default NativeComponentRegistry.get(nativeComponentName, () => __INTERNAL_VIEW_CONFIG);
`.trim();
}; // Check whether the native component exists in the app binary.
// Old getViewManagerConfig() checks for the existance of the native Paper view manager. Not available in Bridgeless.
// New hasViewManagerConfig() queries Fabric’s native component registry directly.
const deprecatedComponentTemplate = `
if (UIManager.getViewManagerConfig('::_COMPONENT_NAME_::')) {
nativeComponentName = '::_COMPONENT_NAME_::';
} else if (UIManager.getViewManagerConfig('::_COMPONENT_NAME_DEPRECATED_::')) {
nativeComponentName = '::_COMPONENT_NAME_DEPRECATED_::';
const DeprecatedComponentNameCheckTemplate = ({
componentName,
paperComponentNameDeprecated
}) => `
if (UIManager.hasViewManagerConfig('${componentName}')) {
nativeComponentName = '${componentName}';
} else if (UIManager.hasViewManagerConfig('${paperComponentNameDeprecated}')) {
nativeComponentName = '${paperComponentNameDeprecated}';
} else {
throw new Error('Failed to find native component for either "::_COMPONENT_NAME_::" or "::_COMPONENT_NAME_DEPRECATED_::"');
throw new Error('Failed to find native component for either "${componentName}" or "${paperComponentNameDeprecated}"');
}
`.trim();
`.trim(); // Replicates the behavior of RCTNormalizeInputEventName in RCTEventDispatcher.m
// Replicates the behavior of RCTNormalizeInputEventName in RCTEventDispatcher.m
function normalizeInputEventName(name) {

@@ -125,55 +150,24 @@ if (name.startsWith('on')) {

return name;
}
} // Replicates the behavior of viewConfig in RCTComponentData.m
// Replicates the behavior of viewConfig in RCTComponentData.m
function getValidAttributesForEvents(events) {
return events.map(eventType => {
function getValidAttributesForEvents(events, imports) {
imports.add("const {ConditionallyIgnoredEventHandlers} = require('react-native/Libraries/NativeComponent/ViewConfigIgnore');");
const validAttributes = j.objectExpression(events.map(eventType => {
return j.property('init', j.identifier(eventType.name), j.literal(true));
});
}));
return j.callExpression(j.identifier('ConditionallyIgnoredEventHandlers'), [validAttributes]);
}
function generateBubblingEventInfo(event, nameOveride) {
return j.property(
'init',
j.identifier(nameOveride || normalizeInputEventName(event.name)),
j.objectExpression([
j.property(
'init',
j.identifier('phasedRegistrationNames'),
j.objectExpression([
j.property(
'init',
j.identifier('captured'),
j.literal(`${event.name}Capture`),
),
j.property('init', j.identifier('bubbled'), j.literal(event.name)),
]),
),
]),
);
return j.property('init', j.identifier(nameOveride || normalizeInputEventName(event.name)), j.objectExpression([j.property('init', j.identifier('phasedRegistrationNames'), j.objectExpression([j.property('init', j.identifier('captured'), j.literal(`${event.name}Capture`)), j.property('init', j.identifier('bubbled'), j.literal(event.name))]))]));
}
function generateDirectEventInfo(event, nameOveride) {
return j.property(
'init',
j.identifier(nameOveride || normalizeInputEventName(event.name)),
j.objectExpression([
j.property(
'init',
j.identifier('registrationName'),
j.literal(event.name),
),
]),
);
return j.property('init', j.identifier(nameOveride || normalizeInputEventName(event.name)), j.objectExpression([j.property('init', j.identifier('registrationName'), j.literal(event.name))]));
}
function buildViewConfig(
schema ,
componentName ,
component,
imports,
) {
function buildViewConfig(schema, componentName, component, imports) {
const componentProps = component.props;
const componentEvents = component.events;
component.extendsProps.forEach(extendProps => {

@@ -184,96 +178,49 @@ switch (extendProps.type) {

case 'ReactNativeCoreViewProps':
imports.add(
"const NativeComponentRegistry = require('NativeComponentRegistry');",
);
imports.add("const NativeComponentRegistry = require('react-native/Libraries/NativeComponent/NativeComponentRegistry');");
return;
return;
default:
(extendProps.knownTypeName );
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
default:
(extendProps.type );
extendProps.type;
throw new Error('Invalid extended type');
}
});
const validAttributes = j.objectExpression([
...componentProps.map(schemaProp => {
return j.property(
'init',
j.identifier(schemaProp.name),
getReactDiffProcessValue(schemaProp.typeAnnotation),
);
}),
...getValidAttributesForEvents(componentEvents),
]);
const bubblingEventNames = component.events
.filter(event => event.bubblingType === 'bubble')
.reduce((bubblingEvents, event) => {
// We add in the deprecated paper name so that it is in the view config.
// This means either the old event name or the new event name can fire
// and be sent to the listener until the old top level name is removed.
if (event.paperTopLevelNameDeprecated) {
bubblingEvents.push(
generateBubblingEventInfo(event, event.paperTopLevelNameDeprecated),
);
}
const validAttributes = j.objectExpression([...componentProps.map(schemaProp => {
return j.property('init', j.identifier(schemaProp.name), getReactDiffProcessValue(schemaProp.typeAnnotation));
}), ...(componentEvents.length > 0 ? [j.spreadProperty(getValidAttributesForEvents(componentEvents, imports))] : [])]);
const bubblingEventNames = component.events.filter(event => event.bubblingType === 'bubble').reduce((bubblingEvents, event) => {
// We add in the deprecated paper name so that it is in the view config.
// This means either the old event name or the new event name can fire
// and be sent to the listener until the old top level name is removed.
if (event.paperTopLevelNameDeprecated) {
bubblingEvents.push(generateBubblingEventInfo(event, event.paperTopLevelNameDeprecated));
} else {
bubblingEvents.push(generateBubblingEventInfo(event));
return bubblingEvents;
}, []);
}
const bubblingEvents =
bubblingEventNames.length > 0
? j.property(
'init',
j.identifier('bubblingEventTypes'),
j.objectExpression(bubblingEventNames),
)
: null;
const directEventNames = component.events
.filter(event => event.bubblingType === 'direct')
.reduce((directEvents, event) => {
// We add in the deprecated paper name so that it is in the view config.
// This means either the old event name or the new event name can fire
// and be sent to the listener until the old top level name is removed.
if (event.paperTopLevelNameDeprecated) {
directEvents.push(
generateDirectEventInfo(event, event.paperTopLevelNameDeprecated),
);
}
return bubblingEvents;
}, []);
const bubblingEvents = bubblingEventNames.length > 0 ? j.property('init', j.identifier('bubblingEventTypes'), j.objectExpression(bubblingEventNames)) : null;
const directEventNames = component.events.filter(event => event.bubblingType === 'direct').reduce((directEvents, event) => {
// We add in the deprecated paper name so that it is in the view config.
// This means either the old event name or the new event name can fire
// and be sent to the listener until the old top level name is removed.
if (event.paperTopLevelNameDeprecated) {
directEvents.push(generateDirectEventInfo(event, event.paperTopLevelNameDeprecated));
} else {
directEvents.push(generateDirectEventInfo(event));
return directEvents;
}, []);
}
const directEvents =
directEventNames.length > 0
? j.property(
'init',
j.identifier('directEventTypes'),
j.objectExpression(directEventNames),
)
: null;
const properties = [
j.property(
'init',
j.identifier('uiViewClassName'),
j.literal(componentName),
),
bubblingEvents,
directEvents,
j.property('init', j.identifier('validAttributes'), validAttributes),
].filter(Boolean);
return directEvents;
}, []);
const directEvents = directEventNames.length > 0 ? j.property('init', j.identifier('directEventTypes'), j.objectExpression(directEventNames)) : null;
const properties = [j.property('init', j.identifier('uiViewClassName'), j.literal(componentName)), bubblingEvents, directEvents, j.property('init', j.identifier('validAttributes'), validAttributes)].filter(Boolean);
return j.objectExpression(properties);
}
function buildCommands(
schema ,
componentName ,
component,
imports,
) {
function buildCommands(schema, componentName, component, imports) {
const commands = component.commands;

@@ -285,141 +232,71 @@

imports.add(
'const {dispatchCommand} = require("react-native/Libraries/Renderer/shims/ReactNative");',
);
imports.add('const {dispatchCommand} = require("react-native/Libraries/ReactNative/RendererProxy");');
const properties = commands.map(command => {
const commandName = command.name;
const params = command.typeAnnotation.params;
const commandNameLiteral = j.literal(commandName);
const commandNameIdentifier = j.identifier(commandName);
const arrayParams = j.arrayExpression(
params.map(param => {
return j.identifier(param.name);
}),
);
const expression = j.template
.expression`dispatchCommand(ref, ${commandNameLiteral}, ${arrayParams})`;
const arrayParams = j.arrayExpression(params.map(param => {
return j.identifier(param.name);
}));
const expression = j.template.expression`dispatchCommand(ref, ${commandNameLiteral}, ${arrayParams})`;
const functionParams = params.map(param => {
return j.identifier(param.name);
});
const property = j.property(
'init',
commandNameIdentifier,
j.functionExpression(
null,
[j.identifier('ref'), ...functionParams],
j.blockStatement([j.expressionStatement(expression)]),
),
);
const property = j.property('init', commandNameIdentifier, j.functionExpression(null, [j.identifier('ref'), ...functionParams], j.blockStatement([j.expressionStatement(expression)])));
property.method = true;
return property;
});
return j.exportNamedDeclaration(
j.variableDeclaration('const', [
j.variableDeclarator(
j.identifier('Commands'),
j.objectExpression(properties),
),
]),
);
return j.exportNamedDeclaration(j.variableDeclaration('const', [j.variableDeclarator(j.identifier('Commands'), j.objectExpression(properties))]));
}
module.exports = {
generate(libraryName , schema ) {
generate(libraryName, schema) {
try {
const fileName = `${libraryName}NativeViewConfig.js`;
const imports = new Set();
const imports = new Set();
const moduleResults = Object.keys(schema.modules).map(moduleName => {
const module = schema.modules[moduleName];
const moduleResults = Object.keys(schema.modules)
.map(moduleName => {
const module = schema.modules[moduleName];
if (module.type !== 'Component') {
return;
}
if (module.type !== 'Component') {
return;
}
const {components} = module;
const components = module.components;
return Object.keys(components).map(componentName => {
var _component$paperCompo;
return Object.keys(components)
.map((componentName ) => {
const component = components[componentName];
const component = components[componentName];
const paperComponentName = component.paperComponentName
? component.paperComponentName
: componentName;
if (component.paperComponentNameDeprecated) {
imports.add(UIMANAGER_IMPORT);
}
if (component.paperComponentNameDeprecated) {
imports.add(UIMANAGER_IMPORT);
}
const replacedTemplate = ComponentTemplate({
componentName,
paperComponentName: component.paperComponentName,
paperComponentNameDeprecated: component.paperComponentNameDeprecated
});
const replacedSourceRoot = j.withParser('flow')(replacedTemplate);
const paperComponentName = (_component$paperCompo = component.paperComponentName) !== null && _component$paperCompo !== void 0 ? _component$paperCompo : componentName;
replacedSourceRoot.find(j.Identifier, {
name: 'VIEW_CONFIG'
}).replaceWith(buildViewConfig(schema, paperComponentName, component, imports));
const commands = buildCommands(schema, paperComponentName, component, imports);
const deprecatedCheckBlock = component.paperComponentNameDeprecated
? deprecatedComponentTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace(
/::_COMPONENT_NAME_DEPRECATED_::/g,
component.paperComponentNameDeprecated || '',
)
: '';
if (commands) {
replacedSourceRoot.find(j.ExportDefaultDeclaration).insertAfter(j(commands).toSource());
}
const replacedTemplate = componentTemplate
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace(
/::_COMPONENT_NAME_WITH_COMPAT_SUPPORT_::/g,
paperComponentName,
)
.replace(/::_DEPRECATION_CHECK_::/, deprecatedCheckBlock);
const replacedSourceRoot = j.withParser('flow')(replacedTemplate);
replacedSourceRoot
.find(j.Identifier, {
name: 'VIEW_CONFIG',
})
.replaceWith(
buildViewConfig(
schema,
paperComponentName,
component,
imports,
),
);
const commands = buildCommands(
schema,
paperComponentName,
component,
imports,
);
if (commands) {
replacedSourceRoot
.find(j.ExportDefaultDeclaration)
.insertAfter(j(commands).toSource());
}
const replacedSource = replacedSourceRoot.toSource({
quote: 'single',
trailingComma: true,
});
return replacedSource;
})
.join('\n\n');
})
.filter(Boolean)
.join('\n\n');
const replacedTemplate = template
.replace(/::_COMPONENT_CONFIG_::/g, moduleResults)
.replace(
'::_IMPORTS_::',
Array.from(imports)
.sort()
.join('\n'),
);
const replacedSource = replacedSourceRoot.toSource({
quote: 'single',
trailingComma: true
});
return replacedSource;
}).join('\n\n');
}).filter(Boolean).join('\n\n');
const replacedTemplate = FileTemplate({
componentConfig: moduleResults,
imports: Array.from(imports).sort().join('\n')
});
return new Map([[fileName, replacedTemplate]]);

@@ -431,3 +308,4 @@ } catch (error) {

}
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,23 +10,17 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function upperCaseFirst(inString ) {
function upperCaseFirst(inString) {
return inString[0].toUpperCase() + inString.slice(1);
}
function getInterfaceJavaClassName(componentName ) {
function getInterfaceJavaClassName(componentName) {
return `${componentName.replace(/^RCT/, '')}ManagerInterface`;
}
function getDelegateJavaClassName(componentName ) {
function getDelegateJavaClassName(componentName) {
return `${componentName.replace(/^RCT/, '')}ManagerDelegate`;
}
function toSafeJavaString(
input ,
shouldUpperCaseFirst ,
) {
function toSafeJavaString(input, shouldUpperCaseFirst) {
const parts = input.split('-');

@@ -41,8 +35,4 @@

function getImports(
component ,
type ,
) {
const imports = new Set();
function getImports(component, type) {
const imports = new Set();
component.extendsProps.forEach(extendProps => {

@@ -55,8 +45,10 @@ switch (extendProps.type) {

return;
default:
(extendProps.knownTypeName );
extendProps.knownTypeName;
throw new Error('Invalid knownTypeName');
}
default:
(extendProps.type );
extendProps.type;
throw new Error('Invalid extended type');

@@ -72,14 +64,19 @@ }

}
return;
case 'ImageSourcePrimitive':
imports.add('import com.facebook.react.bridge.ReadableMap;');
return;
case 'PointPrimitive':
imports.add('import com.facebook.react.bridge.ReadableMap;');
return;
case 'EdgeInsetsPrimitive':
imports.add('import com.facebook.react.bridge.ReadableMap;');
return;
default:
(name );
name;
throw new Error(`Invalid ReservedPropTypeAnnotation name, got ${name}`);

@@ -104,3 +101,2 @@ }

});
return imports;

@@ -113,3 +109,3 @@ }

toSafeJavaString,
getImports,
};
getImports
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,38 +10,31 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('./Utils'),
createAliasResolver = _require.createAliasResolver,
getModules = _require.getModules;
const _require2 = require('../../parsers/parsers-commons'),
unwrapNullable = _require2.unwrapNullable;
const HostFunctionTemplate = ({
hasteModuleName,
methodName,
isVoid,
args,
}
) => {
returnTypeAnnotation,
args
}) => {
const isNullable = returnTypeAnnotation.type === 'NullableTypeAnnotation';
const isVoid = returnTypeAnnotation.type === 'VoidTypeAnnotation';
const methodCallArgs = ['rt', ...args].join(', ');
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs});`;
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${
isVoid ? `\n ${methodCall}` : ''
}
return ${isVoid ? 'jsi::Value::undefined();' : methodCall}
const methodCall = `static_cast<${hasteModuleName}CxxSpecJSI *>(&turboModule)->${methodName}(${methodCallArgs})`;
return `static jsi::Value __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {${isVoid ? `\n ${methodCall};` : isNullable ? `\n auto result = ${methodCall};` : ''}
return ${isVoid ? 'jsi::Value::undefined()' : isNullable ? 'result ? jsi::Value(std::move(*result)) : jsi::Value::null()' : methodCall};
}`;

@@ -54,9 +47,4 @@ };

moduleName,
methods,
}
) => {
methods
}) => {
return `${hostFunctions.join('\n')}

@@ -66,7 +54,8 @@

: TurboModule("${moduleName}", jsInvoker) {
${methods
.map(({methodName, paramCount}) => {
${methods.map(({
methodName,
paramCount
}) => {
return ` methodMap_["${methodName}"] = MethodMetadata {${paramCount}, __hostFunction_${hasteModuleName}CxxSpecJSI_${methodName}};`;
})
.join('\n')}
}).join('\n')}
}`;

@@ -77,12 +66,9 @@ };

libraryName,
modules,
}
) => {
modules
}) => {
return `/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -92,3 +78,3 @@ * ${'@'}generated by codegen project: GenerateModuleH.js

#include <react/modules/${libraryName}/NativeModules.h>
#include "${libraryName}JSI.h"

@@ -106,18 +92,14 @@ namespace facebook {

function serializeArg(arg, index, resolveAlias) {
const nullableTypeAnnotation = arg.typeAnnotation,
optional = arg.optional;
function serializeArg(
arg ,
index ,
resolveAlias ,
) {
function wrap(suffix) {
return `args[${index}]${suffix}`;
}
const {typeAnnotation: nullableTypeAnnotation} = arg;
const [typeAnnotation] = unwrapNullable (
nullableTypeAnnotation,
);
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
const isRequired = !optional && !nullable;
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -127,2 +109,19 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

function wrap(callback) {
const val = `args[${index}]`;
const expression = callback(val);
if (isRequired) {
return expression;
} else {
let condition = `${val}.isNull() || ${val}.isUndefined()`;
if (optional) {
condition = `count < ${index} || ${condition}`;
}
return `${condition} ? std::nullopt : std::make_optional(${expression})`;
}
}
switch (realTypeAnnotation.type) {

@@ -132,49 +131,79 @@ case 'ReservedTypeAnnotation':

case 'RootTag':
return wrap('.getNumber()');
return wrap(val => `${val}.getNumber()`);
default:
(realTypeAnnotation.name );
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`,
);
realTypeAnnotation.name;
throw new Error(`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.name}"`);
}
case 'StringTypeAnnotation':
return wrap('.getString(rt)');
return wrap(val => `${val}.asString(rt)`);
case 'BooleanTypeAnnotation':
return wrap('.getBool()');
return wrap(val => `${val}.asBool()`);
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(`Unknown enum type for "${arg.name}, found: ${realTypeAnnotation.type}"`);
}
case 'NumberTypeAnnotation':
return wrap('.getNumber()');
return wrap(val => `${val}.asNumber()`);
case 'FloatTypeAnnotation':
return wrap('.getNumber()');
return wrap(val => `${val}.asNumber()`);
case 'DoubleTypeAnnotation':
return wrap('.getNumber()');
return wrap(val => `${val}.asNumber()`);
case 'Int32TypeAnnotation':
return wrap('.getNumber()');
return wrap(val => `${val}.asNumber()`);
case 'ArrayTypeAnnotation':
return wrap('.getObject(rt).getArray(rt)');
return wrap(val => `${val}.asObject(rt).asArray(rt)`);
case 'FunctionTypeAnnotation':
return `std::move(${wrap('.getObject(rt).getFunction(rt)')})`;
return wrap(val => `${val}.asObject(rt).asFunction(rt)`);
case 'GenericObjectTypeAnnotation':
return wrap('.getObject(rt)');
return wrap(val => `${val}.asObject(rt)`);
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap(val => `${val}.asNumber()`);
case 'ObjectTypeAnnotation':
return wrap(val => `${val}.asObject(rt)`);
case 'StringTypeAnnotation':
return wrap(val => `${val}.asString(rt)`);
default:
throw new Error(`Unsupported union member type for param "${arg.name}, found: ${realTypeAnnotation.memberType}"`);
}
case 'ObjectTypeAnnotation':
return wrap('.getObject(rt)');
return wrap(val => `${val}.asObject(rt)`);
case 'MixedTypeAnnotation':
return wrap(val => `jsi::Value(rt, ${val})`);
default:
(realTypeAnnotation.type );
throw new Error(
`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`,
);
realTypeAnnotation.type;
throw new Error(`Unknown prop type for "${arg.name}, found: ${realTypeAnnotation.type}"`);
}
}
function serializePropertyIntoHostFunction(
hasteModuleName ,
property ,
resolveAlias ,
) {
const [
propertyTypeAnnotation,
] = unwrapNullable (
property.typeAnnotation,
);
const isVoid =
propertyTypeAnnotation.returnTypeAnnotation.type === 'VoidTypeAnnotation';
function serializePropertyIntoHostFunction(hasteModuleName, property, resolveAlias) {
const _unwrapNullable3 = unwrapNullable(property.typeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 1),
propertyTypeAnnotation = _unwrapNullable4[0];

@@ -184,6 +213,4 @@ return HostFunctionTemplate({

methodName: property.name,
isVoid,
args: propertyTypeAnnotation.params.map((p, i) =>
serializeArg(p, i, resolveAlias),
),
returnTypeAnnotation: propertyTypeAnnotation.returnTypeAnnotation,
args: propertyTypeAnnotation.params.map((p, i) => serializeArg(p, i, resolveAlias))
});

@@ -193,52 +220,39 @@ }

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules).map(hasteModuleName => {
const nativeModule = nativeModules[hasteModuleName];
const aliases = nativeModule.aliases,
properties = nativeModule.spec.properties,
moduleNames = nativeModule.moduleNames;
const resolveAlias = createAliasResolver(aliases);
const hostFunctions = properties.map(property => serializePropertyIntoHostFunction(hasteModuleName, property, resolveAlias));
return ModuleTemplate({
hasteModuleName,
hostFunctions,
// TODO: What happens when there are more than one NativeModule requires?
moduleName: moduleNames[0],
methods: properties.map(({
name: propertyName,
typeAnnotation: nullableTypeAnnotation
}) => {
const _unwrapNullable5 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable6 = _slicedToArray(_unwrapNullable5, 1),
params = _unwrapNullable6[0].params;
const modules = Object.keys(nativeModules)
.map((hasteModuleName ) => {
const nativeModule = nativeModules[hasteModuleName];
const {
aliases,
spec: {properties},
moduleNames,
} = nativeModule;
const resolveAlias = createAliasResolver(aliases);
const hostFunctions = properties.map(property =>
serializePropertyIntoHostFunction(
hasteModuleName,
property,
resolveAlias,
),
);
return ModuleTemplate({
hasteModuleName,
hostFunctions,
// TODO: What happens when there are more than one NativeModule requires?
moduleName: moduleNames[0],
methods: properties.map(
({name: propertyName, typeAnnotation: nullableTypeAnnotation}) => {
const [{params}] = unwrapNullable(nullableTypeAnnotation);
return {
methodName: propertyName,
paramCount: params.length,
};
},
),
});
})
.join('\n');
const fileName = 'NativeModules.cpp';
return {
methodName: propertyName,
paramCount: params.length
};
})
});
}).join('\n');
const fileName = `${libraryName}JSI-generated.cpp`;
const replacedTemplate = FileTemplate({
modules,
libraryName,
libraryName
});
return new Map([[fileName, replacedTemplate]]);
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,23 +10,28 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('./Utils'),
createAliasResolver = _require.createAliasResolver,
getModules = _require.getModules;
const _require2 = require('../Utils'),
indent = _require2.indent;
const _require3 = require('../../parsers/parsers-commons'),
unwrapNullable = _require3.unwrapNullable;
const ModuleClassDeclarationTemplate = ({
hasteModuleName,
moduleProperties,
} ) => {
return `class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule {
structs
}) => {
return `${structs}class JSI_EXPORT ${hasteModuleName}CxxSpecJSI : public TurboModule {
protected:

@@ -36,3 +41,3 @@ ${hasteModuleName}CxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker);

public:
${moduleProperties}
${indent(moduleProperties.join('\n'), 2)}

@@ -42,12 +47,43 @@ };`;

const ModuleSpecClassDeclarationTemplate = ({
hasteModuleName,
moduleName,
moduleProperties
}) => {
return `template <typename T>
class JSI_EXPORT ${hasteModuleName}CxxSpec : public TurboModule {
public:
jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &propName) override {
return delegate_.get(rt, propName);
}
protected:
${hasteModuleName}CxxSpec(std::shared_ptr<CallInvoker> jsInvoker)
: TurboModule("${moduleName}", jsInvoker),
delegate_(static_cast<T*>(this), jsInvoker) {}
private:
class Delegate : public ${hasteModuleName}CxxSpecJSI {
public:
Delegate(T *instance, std::shared_ptr<CallInvoker> jsInvoker) :
${hasteModuleName}CxxSpecJSI(std::move(jsInvoker)), instance_(instance) {}
${indent(moduleProperties.join('\n'), 4)}
private:
T *instance_;
};
Delegate delegate_;
};`;
};
const FileTemplate = ({
modules,
}
) => {
modules
}) => {
return `/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -60,7 +96,9 @@ * ${'@'}generated by codegen project: GenerateModuleH.js

#include <ReactCommon/TurboModule.h>
#include <react/bridging/Bridging.h>
namespace facebook {
namespace react {
${modules}
${modules.join('\n\n')}
} // namespace react

@@ -71,11 +109,11 @@ } // namespace facebook

function translatePrimitiveJSTypeToCpp(
nullableTypeAnnotation ,
createErrorMessage ,
resolveAlias ,
) {
const [typeAnnotation] = unwrapNullable (
nullableTypeAnnotation,
);
function translatePrimitiveJSTypeToCpp(nullableTypeAnnotation, optional, createErrorMessage, resolveAlias) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
const isRequired = !optional && !nullable;
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -85,2 +123,6 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

function wrap(type) {
return isRequired ? type : `std::optional<${type}>`;
}
switch (realTypeAnnotation.type) {

@@ -90,33 +132,77 @@ case 'ReservedTypeAnnotation':

case 'RootTag':
return 'double';
return wrap('double');
default:
(realTypeAnnotation.name );
realTypeAnnotation.name;
throw new Error(createErrorMessage(realTypeAnnotation.name));
}
case 'VoidTypeAnnotation':
return 'void';
case 'StringTypeAnnotation':
return 'jsi::String';
return wrap('jsi::String');
case 'NumberTypeAnnotation':
return 'double';
return wrap('double');
case 'DoubleTypeAnnotation':
return 'double';
return wrap('double');
case 'FloatTypeAnnotation':
return 'double';
return wrap('double');
case 'Int32TypeAnnotation':
return 'int';
return wrap('int');
case 'BooleanTypeAnnotation':
return 'bool';
return wrap('bool');
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap('double');
case 'StringTypeAnnotation':
return wrap('jsi::String');
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'GenericObjectTypeAnnotation':
return 'jsi::Object';
return wrap('jsi::Object');
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrap('double');
case 'ObjectTypeAnnotation':
return wrap('jsi::Object');
case 'StringTypeAnnotation':
return wrap('jsi::String');
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'ObjectTypeAnnotation':
return 'jsi::Object';
return wrap('jsi::Object');
case 'ArrayTypeAnnotation':
return 'jsi::Array';
return wrap('jsi::Array');
case 'FunctionTypeAnnotation':
return 'jsi::Function';
return wrap('jsi::Function');
case 'PromiseTypeAnnotation':
return 'jsi::Value';
return wrap('jsi::Value');
case 'MixedTypeAnnotation':
return wrap('jsi::Value');
default:
(realTypeAnnotation.type );
realTypeAnnotation.type;
throw new Error(createErrorMessage(realTypeAnnotation.type));

@@ -126,75 +212,113 @@ }

const propertyTemplate =
'virtual ::_RETURN_VALUE_:: ::_PROPERTY_NAME_::(jsi::Runtime &rt::_ARGS_::) = 0;';
function createStructs(moduleName, aliasMap, resolveAlias) {
return Object.keys(aliasMap).map(alias => {
const value = aliasMap[alias];
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
const nativeModules = getModules(schema);
if (value.properties.length === 0) {
return '';
}
const modules = Object.keys(nativeModules)
.map(hasteModuleName => {
const {
aliases,
spec: {properties},
} = nativeModules[hasteModuleName];
const resolveAlias = createAliasResolver(aliases);
const structName = `${moduleName}Base${alias}`;
const templateParameterWithTypename = value.properties.map((v, i) => 'typename P' + i).join(', ');
const templateParameter = value.properties.map((v, i) => 'P' + i).join(', ');
return `#pragma mark - ${structName}
const traversedProperties = properties
.map(prop => {
const [
propTypeAnnotation,
] = unwrapNullable (
prop.typeAnnotation,
);
const traversedArgs = propTypeAnnotation.params
.map(param => {
const translatedParam = translatePrimitiveJSTypeToCpp(
param.typeAnnotation,
typeName =>
`Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`,
resolveAlias,
);
const isObject = translatedParam.startsWith('jsi::');
return (
(isObject
? 'const ' + translatedParam + ' &'
: translatedParam + ' ') + param.name
);
})
.join(', ');
return propertyTemplate
.replace('::_PROPERTY_NAME_::', prop.name)
.replace(
'::_RETURN_VALUE_::',
translatePrimitiveJSTypeToCpp(
propTypeAnnotation.returnTypeAnnotation,
typeName =>
`Unsupported return type for ${prop.name}. Found: ${typeName}`,
resolveAlias,
),
)
.replace(
'::_ARGS_::',
traversedArgs === '' ? '' : ', ' + traversedArgs,
);
})
.join('\n');
template <${templateParameterWithTypename}>
struct ${structName} {
${value.properties.map((v, i) => ' P' + i + ' ' + v.name).join(';\n')};
bool operator==(const ${structName} &other) const {
return ${value.properties.map(v => `${v.name} == other.${v.name}`).join(' && ')};
}
};
return ModuleClassDeclarationTemplate({
hasteModuleName,
moduleProperties: traversedProperties,
});
})
.join('\n');
template <${templateParameterWithTypename}>
struct ${structName}Bridging {
static ${structName}<${templateParameter}> fromJs(
jsi::Runtime &rt,
const jsi::Object &value,
const std::shared_ptr<CallInvoker> &jsInvoker) {
${structName}<${templateParameter}> result{
${value.properties.map((v, i) => ` bridging::fromJs<P${i}>(rt, value.getProperty(rt, "${v.name}"), jsInvoker)`).join(',\n')}};
return result;
}
const fileName = 'NativeModules.h';
const replacedTemplate = FileTemplate({modules});
static jsi::Object toJs(
jsi::Runtime &rt,
const ${structName}<${templateParameter}> &value) {
auto result = facebook::jsi::Object(rt);
${value.properties.map((v, i) => {
if (v.optional) {
return ` if (value.${v.name}) {
result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}.value()));
}`;
} else {
return ` result.setProperty(rt, "${v.name}", bridging::toJs(rt, value.${v.name}));`;
}
}).join('\n')}
return result;
}
};
`;
}).join('\n');
}
function translatePropertyToCpp(prop, resolveAlias, abstract = false) {
const _unwrapNullable3 = unwrapNullable(prop.typeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 1),
propTypeAnnotation = _unwrapNullable4[0];
const params = propTypeAnnotation.params.map(param => `std::move(${param.name})`);
const paramTypes = propTypeAnnotation.params.map(param => {
const translatedParam = translatePrimitiveJSTypeToCpp(param.typeAnnotation, param.optional, typeName => `Unsupported type for param "${param.name}" in ${prop.name}. Found: ${typeName}`, resolveAlias);
return `${translatedParam} ${param.name}`;
});
const returnType = translatePrimitiveJSTypeToCpp(propTypeAnnotation.returnTypeAnnotation, false, typeName => `Unsupported return type for ${prop.name}. Found: ${typeName}`, resolveAlias); // The first param will always be the runtime reference.
paramTypes.unshift('jsi::Runtime &rt');
const method = `${returnType} ${prop.name}(${paramTypes.join(', ')})`;
if (abstract) {
return `virtual ${method} = 0;`;
}
return `${method} override {
static_assert(
bridging::getParameterCount(&T::${prop.name}) == ${paramTypes.length},
"Expected ${prop.name}(...) to have ${paramTypes.length} parameters");
return bridging::callFromJs<${returnType}>(
rt, &T::${prop.name}, jsInvoker_, ${['instance_', ...params].join(', ')});
}`;
}
module.exports = {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules).flatMap(hasteModuleName => {
const _nativeModules$hasteM = nativeModules[hasteModuleName],
aliases = _nativeModules$hasteM.aliases,
properties = _nativeModules$hasteM.spec.properties,
_nativeModules$hasteM2 = _slicedToArray(_nativeModules$hasteM.moduleNames, 1),
moduleName = _nativeModules$hasteM2[0];
const resolveAlias = createAliasResolver(aliases);
const structs = createStructs(moduleName, aliases, resolveAlias);
return [ModuleClassDeclarationTemplate({
hasteModuleName,
moduleProperties: properties.map(prop => translatePropertyToCpp(prop, resolveAlias, true)),
structs
}), ModuleSpecClassDeclarationTemplate({
hasteModuleName,
moduleName,
moduleProperties: properties.map(prop => translatePropertyToCpp(prop, resolveAlias))
})];
});
const fileName = `${libraryName}JSI.h`;
const replacedTemplate = FileTemplate({
modules
});
return new Map([[fileName, replacedTemplate]]);
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,40 +10,34 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function FileTemplate(
config
,
) {
const {packageName, className, methods, imports} = config;
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('./Utils'),
createAliasResolver = _require.createAliasResolver,
getModules = _require.getModules;
const _require2 = require('../../parsers/parsers-commons'),
unwrapNullable = _require2.unwrapNullable;
function FileTemplate(config) {
const packageName = config.packageName,
className = config.className,
methods = config.methods,
imports = config.imports;
return `
/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*
* ${'@'}generated by codegen project: GenerateModuleJavaSpec.js
*
* @nolint
* ${'@'}nolint
*/

@@ -65,56 +59,40 @@

function MethodTemplate(
config
,
) {
const {
abstract,
methodBody,
methodJavaAnnotation,
methodName,
translatedReturnType,
traversedArgs,
} = config;
function MethodTemplate(config) {
const abstract = config.abstract,
methodBody = config.methodBody,
methodJavaAnnotation = config.methodJavaAnnotation,
methodName = config.methodName,
translatedReturnType = config.translatedReturnType,
traversedArgs = config.traversedArgs;
const methodQualifier = abstract ? 'abstract ' : '';
const methodClosing = abstract
? ';'
: methodBody != null && methodBody.length > 0
? ` { ${methodBody} }`
: ' {}';
const methodClosing = abstract ? ';' : methodBody != null && methodBody.length > 0 ? ` { ${methodBody} }` : ' {}';
return ` ${methodJavaAnnotation}
public ${methodQualifier}${translatedReturnType} ${methodName}(${traversedArgs.join(
', ',
)})${methodClosing}`;
public ${methodQualifier}${translatedReturnType} ${methodName}(${traversedArgs.join(', ')})${methodClosing}`;
}
function translateFunctionParamToJavaType(param, createErrorMessage, resolveAlias, imports) {
const optional = param.optional,
nullableTypeAnnotation = param.typeAnnotation;
function translateFunctionParamToJavaType(
param ,
createErrorMessage ,
resolveAlias ,
imports ,
) {
const {optional, typeAnnotation: nullableTypeAnnotation} = param;
const [
typeAnnotation,
nullable,
] = unwrapNullable (nullableTypeAnnotation);
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
const isRequired = !optional && !nullable;
function wrapIntoNullableIfNeeded(generatedType ) {
function wrapNullable(javaType, nullableType) {
if (!isRequired) {
var _nullableType;
imports.add('javax.annotation.Nullable');
return `@Nullable ${generatedType}`;
return `@Nullable ${(_nullableType = nullableType) !== null && _nullableType !== void 0 ? _nullableType : javaType}`;
}
return generatedType;
}
return javaType;
} // FIXME: support class alias for args
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -128,38 +106,74 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

case 'RootTag':
return !isRequired ? 'Double' : 'double';
return wrapNullable('double', 'Double');
default:
(realTypeAnnotation.name );
realTypeAnnotation.name;
throw new Error(createErrorMessage(realTypeAnnotation.name));
}
case 'StringTypeAnnotation':
return wrapIntoNullableIfNeeded('String');
return wrapNullable('String');
case 'NumberTypeAnnotation':
return !isRequired ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'FloatTypeAnnotation':
return !isRequired ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'DoubleTypeAnnotation':
return !isRequired ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'Int32TypeAnnotation':
return !isRequired ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'BooleanTypeAnnotation':
return !isRequired ? 'Boolean' : 'boolean';
return wrapNullable('boolean', 'Boolean');
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
return wrapNullable('ReadableMap');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`);
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableMap');
if (typeAnnotation.type === 'TypeAliasTypeAnnotation') {
// No class alias for args, so it still falls under ReadableMap.
return 'ReadableMap';
}
return 'ReadableMap';
return wrapNullable('ReadableMap');
case 'GenericObjectTypeAnnotation':
// Treat this the same as ObjectTypeAnnotation for now.
imports.add('com.facebook.react.bridge.ReadableMap');
return 'ReadableMap';
return wrapNullable('ReadableMap');
case 'ArrayTypeAnnotation':
imports.add('com.facebook.react.bridge.ReadableArray');
return 'ReadableArray';
return wrapNullable('ReadableArray');
case 'FunctionTypeAnnotation':
imports.add('com.facebook.react.bridge.Callback');
return 'Callback';
return wrapNullable('Callback');
default:
(realTypeAnnotation.type );
realTypeAnnotation.type;
throw new Error(createErrorMessage(realTypeAnnotation.type));

@@ -169,24 +183,22 @@ }

function translateFunctionReturnTypeToJavaType(
nullableReturnTypeAnnotation ,
createErrorMessage ,
resolveAlias ,
imports ,
) {
const [
returnTypeAnnotation,
nullable,
] = unwrapNullable (
nullableReturnTypeAnnotation,
);
function translateFunctionReturnTypeToJavaType(nullableReturnTypeAnnotation, createErrorMessage, resolveAlias, imports) {
const _unwrapNullable3 = unwrapNullable(nullableReturnTypeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2),
returnTypeAnnotation = _unwrapNullable4[0],
nullable = _unwrapNullable4[1];
function wrapIntoNullableIfNeeded(generatedType ) {
function wrapNullable(javaType, nullableType) {
if (nullable) {
var _nullableType2;
imports.add('javax.annotation.Nullable');
return `@Nullable ${generatedType}`;
return `@Nullable ${(_nullableType2 = nullableType) !== null && _nullableType2 !== void 0 ? _nullableType2 : javaType}`;
}
return generatedType;
}
return javaType;
} // FIXME: support class alias for args
let realTypeAnnotation = returnTypeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -200,34 +212,75 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

case 'RootTag':
return nullable ? 'Double' : 'double';
return wrapNullable('double', 'Double');
default:
(realTypeAnnotation.name );
realTypeAnnotation.name;
throw new Error(createErrorMessage(realTypeAnnotation.name));
}
case 'VoidTypeAnnotation':
return 'void';
case 'PromiseTypeAnnotation':
return 'void';
case 'StringTypeAnnotation':
return wrapIntoNullableIfNeeded('String');
return wrapNullable('String');
case 'NumberTypeAnnotation':
return nullable ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'FloatTypeAnnotation':
return nullable ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'DoubleTypeAnnotation':
return nullable ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'Int32TypeAnnotation':
return nullable ? 'Double' : 'double';
return wrapNullable('double', 'Double');
case 'BooleanTypeAnnotation':
return nullable ? 'Boolean' : 'boolean';
return wrapNullable('boolean', 'Boolean');
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapNullable('double', 'Double');
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return wrapNullable('WritableMap');
case 'StringTypeAnnotation':
return wrapNullable('String');
default:
throw new Error(`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`);
}
case 'ObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return 'WritableMap';
return wrapNullable('WritableMap');
case 'GenericObjectTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableMap');
return 'WritableMap';
return wrapNullable('WritableMap');
case 'ArrayTypeAnnotation':
imports.add('com.facebook.react.bridge.WritableArray');
return 'WritableArray';
return wrapNullable('WritableArray');
default:
(realTypeAnnotation.type );
realTypeAnnotation.type;
throw new Error(createErrorMessage(realTypeAnnotation.type));

@@ -237,15 +290,10 @@ }

function getFalsyReturnStatementFromReturnType(
nullableReturnTypeAnnotation ,
createErrorMessage ,
resolveAlias ,
) {
const [
returnTypeAnnotation,
nullable,
] = unwrapNullable (
nullableReturnTypeAnnotation,
);
function getFalsyReturnStatementFromReturnType(nullableReturnTypeAnnotation, createErrorMessage, resolveAlias) {
const _unwrapNullable5 = unwrapNullable(nullableReturnTypeAnnotation),
_unwrapNullable6 = _slicedToArray(_unwrapNullable5, 2),
returnTypeAnnotation = _unwrapNullable6[0],
nullable = _unwrapNullable6[1];
let realTypeAnnotation = returnTypeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -260,49 +308,84 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

return 'return 0.0;';
default:
(realTypeAnnotation.name );
realTypeAnnotation.name;
throw new Error(createErrorMessage(realTypeAnnotation.name));
}
case 'VoidTypeAnnotation':
return '';
case 'PromiseTypeAnnotation':
return '';
case 'NumberTypeAnnotation':
return nullable ? 'return null;' : 'return 0;';
case 'FloatTypeAnnotation':
return nullable ? 'return null;' : 'return 0.0;';
case 'DoubleTypeAnnotation':
return nullable ? 'return null;' : 'return 0.0;';
case 'Int32TypeAnnotation':
return nullable ? 'return null;' : 'return 0;';
case 'BooleanTypeAnnotation':
return nullable ? 'return null;' : 'return false;';
case 'EnumDeclaration':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'return null;' : 'return 0;';
case 'StringTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
default:
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
case 'UnionTypeAnnotation':
switch (realTypeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'return null;' : 'return 0;';
case 'ObjectTypeAnnotation':
return 'return null;';
case 'StringTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
default:
throw new Error(`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`);
}
case 'StringTypeAnnotation':
return nullable ? 'return null;' : 'return "";';
case 'ObjectTypeAnnotation':
return 'return null;';
case 'GenericObjectTypeAnnotation':
return 'return null;';
case 'ArrayTypeAnnotation':
return 'return null;';
default:
(realTypeAnnotation.type );
realTypeAnnotation.type;
throw new Error(createErrorMessage(realTypeAnnotation.type));
}
}
} // Build special-cased runtime check for getConstants().
// Build special-cased runtime check for getConstants().
function buildGetConstantsMethod(
method ,
imports ,
) {
const [
methodTypeAnnotation,
] = unwrapNullable (method.typeAnnotation);
if (
methodTypeAnnotation.returnTypeAnnotation.type === 'ObjectTypeAnnotation'
) {
function buildGetConstantsMethod(method, imports) {
const _unwrapNullable7 = unwrapNullable(method.typeAnnotation),
_unwrapNullable8 = _slicedToArray(_unwrapNullable7, 1),
methodTypeAnnotation = _unwrapNullable8[0];
if (methodTypeAnnotation.returnTypeAnnotation.type === 'ObjectTypeAnnotation') {
const requiredProps = [];
const optionalProps = [];
const rawProperties =
methodTypeAnnotation.returnTypeAnnotation.properties || [];
const rawProperties = methodTypeAnnotation.returnTypeAnnotation.properties || [];
rawProperties.forEach(p => {

@@ -315,2 +398,3 @@ if (p.optional || p.typeAnnotation.type === 'NullableTypeAnnotation') {

});
if (requiredProps.length === 0 && optionalProps.length === 0) {

@@ -327,22 +411,8 @@ // Nothing to validate during runtime.

imports.add('javax.annotation.Nullable');
const requiredPropsFragment =
requiredProps.length > 0
? `Arrays.asList(
${requiredProps
.sort()
.map(p => `"${p}"`)
.join(',\n ')}
)`
: '';
const optionalPropsFragment =
optionalProps.length > 0
? `Arrays.asList(
${optionalProps
.sort()
.map(p => `"${p}"`)
.join(',\n ')}
)`
: '';
const requiredPropsFragment = requiredProps.length > 0 ? `Arrays.asList(
${requiredProps.sort().map(p => `"${p}"`).join(',\n ')}
)` : '';
const optionalPropsFragment = optionalProps.length > 0 ? `Arrays.asList(
${optionalProps.sort().map(p => `"${p}"`).join(',\n ')}
)` : '';
return ` protected abstract Map<String, Object> getTypedExportedConstants();

@@ -377,37 +447,21 @@

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const files = new Map();
const nativeModules = getModules(schema);
const normalizedPackageName =
packageName == null ? 'com.facebook.fbreact.specs' : packageName;
const normalizedPackageName = packageName == null ? 'com.facebook.fbreact.specs' : packageName;
const outputDir = `java/${normalizedPackageName.replace(/\./g, '/')}`;
Object.keys(nativeModules).forEach(hasteModuleName => {
const _nativeModules$hasteM = nativeModules[hasteModuleName],
aliases = _nativeModules$hasteM.aliases,
excludedPlatforms = _nativeModules$hasteM.excludedPlatforms,
properties = _nativeModules$hasteM.spec.properties;
Object.keys(nativeModules).forEach(hasteModuleName => {
const {
aliases,
excludedPlatforms,
spec: {properties},
} = nativeModules[hasteModuleName];
if (excludedPlatforms != null && excludedPlatforms.includes('android')) {
return;
}
const resolveAlias = createAliasResolver(aliases);
const className = `${hasteModuleName}Spec`;
const imports = new Set([
// Always required.
'com.facebook.react.bridge.ReactApplicationContext',
'com.facebook.react.bridge.ReactContextBaseJavaModule',
'com.facebook.react.bridge.ReactMethod',
'com.facebook.react.bridge.ReactModuleWithSpec',
'com.facebook.react.turbomodule.core.interfaces.TurboModule',
'com.facebook.proguard.annotations.DoNotStrip',
]);
const imports = new Set([// Always required.
'com.facebook.react.bridge.ReactApplicationContext', 'com.facebook.react.bridge.ReactContextBaseJavaModule', 'com.facebook.react.bridge.ReactMethod', 'com.facebook.react.bridge.ReactModuleWithSpec', 'com.facebook.react.turbomodule.core.interfaces.TurboModule', 'com.facebook.proguard.annotations.DoNotStrip']);
const methods = properties.map(method => {

@@ -418,32 +472,13 @@ if (method.name === 'getConstants') {

const [
methodTypeAnnotation,
] = unwrapNullable (
method.typeAnnotation,
);
const _unwrapNullable9 = unwrapNullable(method.typeAnnotation),
_unwrapNullable10 = _slicedToArray(_unwrapNullable9, 1),
methodTypeAnnotation = _unwrapNullable10[0]; // Handle return type
// Handle return type
const translatedReturnType = translateFunctionReturnTypeToJavaType(
methodTypeAnnotation.returnTypeAnnotation,
typeName =>
`Unsupported return type for method ${method.name}. Found: ${typeName}`,
resolveAlias,
imports,
);
const returningPromise =
methodTypeAnnotation.returnTypeAnnotation.type ===
'PromiseTypeAnnotation';
const isSyncMethod =
methodTypeAnnotation.returnTypeAnnotation.type !==
'VoidTypeAnnotation' && !returningPromise;
// Handle method args
const translatedReturnType = translateFunctionReturnTypeToJavaType(methodTypeAnnotation.returnTypeAnnotation, typeName => `Unsupported return type for method ${method.name}. Found: ${typeName}`, resolveAlias, imports);
const returningPromise = methodTypeAnnotation.returnTypeAnnotation.type === 'PromiseTypeAnnotation';
const isSyncMethod = methodTypeAnnotation.returnTypeAnnotation.type !== 'VoidTypeAnnotation' && !returningPromise; // Handle method args
const traversedArgs = methodTypeAnnotation.params.map(param => {
const translatedParam = translateFunctionParamToJavaType(
param,
typeName =>
`Unsupported type for param "${param.name}" in ${method.name}. Found: ${typeName}`,
resolveAlias,
imports,
);
const translatedParam = translateFunctionParamToJavaType(param, typeName => `Unsupported type for param "${param.name}" in ${method.name}. Found: ${typeName}`, resolveAlias, imports);
return `${translatedParam} ${param.name}`;

@@ -458,13 +493,4 @@ });

const methodJavaAnnotation = `@ReactMethod${
isSyncMethod ? '(isBlockingSynchronousMethod = true)' : ''
}\n @DoNotStrip`;
const methodBody = method.optional
? getFalsyReturnStatementFromReturnType(
methodTypeAnnotation.returnTypeAnnotation,
typeName =>
`Cannot build falsy return statement for return type for method ${method.name}. Found: ${typeName}`,
resolveAlias,
)
: null;
const methodJavaAnnotation = `@ReactMethod${isSyncMethod ? '(isBlockingSynchronousMethod = true)' : ''}\n @DoNotStrip`;
const methodBody = method.optional ? getFalsyReturnStatementFromReturnType(methodTypeAnnotation.returnTypeAnnotation, typeName => `Cannot build falsy return statement for return type for method ${method.name}. Found: ${typeName}`, resolveAlias) : null;
return MethodTemplate({

@@ -476,22 +502,15 @@ abstract: !method.optional,

translatedReturnType,
traversedArgs,
traversedArgs
});
});
files.set(
`${outputDir}/${className}.java`,
FileTemplate({
packageName: normalizedPackageName,
className,
methods: methods.filter(Boolean).join('\n\n'),
imports: Array.from(imports)
.sort()
.map(p => `import ${p};`)
.join('\n'),
}),
);
files.set(`${outputDir}/${className}.java`, FileTemplate({
packageName: normalizedPackageName,
className,
methods: methods.filter(Boolean).join('\n\n'),
imports: Array.from(imports).sort().map(p => `import ${p};`).join('\n')
}));
});
return files;
}
return files;
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,30 +10,19 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
const {createAliasResolver, getModules} = require('./Utils');
const {unwrapNullable} = require('../../parsers/flow/modules/utils');
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('./Utils'),
createAliasResolver = _require.createAliasResolver,
getModules = _require.getModules;
const _require2 = require('../../parsers/parsers-commons'),
unwrapNullable = _require2.unwrapNullable;
const HostFunctionTemplate = ({

@@ -43,11 +32,7 @@ hasteModuleName,

jniSignature,
jsReturnType,
}
) => {
jsReturnType
}) => {
return `static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${propertyName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count);
static jmethodID cachedMethodId = nullptr;
return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, ${jsReturnType}, "${propertyName}", "${jniSignature}", args, count, cachedMethodId);
}`;

@@ -58,18 +43,13 @@ };

hasteModuleName,
methods,
}
) => {
methods
}) => {
return `
${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const JavaTurboModule::InitParams &params)
: JavaTurboModule(params) {
${methods
.map(({propertyName, argCount}) => {
${methods.map(({
propertyName,
argCount
}) => {
return ` methodMap_["${propertyName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${propertyName}};`;
})
.join('\n')}
}).join('\n')}
}`.trim();

@@ -80,4 +60,4 @@ };

moduleName,
hasteModuleName,
} ) => {
hasteModuleName
}) => {
return ` if (moduleName == "${moduleName}") {

@@ -92,20 +72,10 @@ return std::make_shared<${hasteModuleName}SpecJSI>(params);

modules,
moduleLookups,
}
) => {
moduleLookups
}) => {
return `
/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -122,3 +92,3 @@ * ${'@'}generated by codegen project: GenerateModuleJniCpp.js

std::shared_ptr<TurboModule> ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params) {
std::shared_ptr<TurboModule> ${libraryName}_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams &params) {
${moduleLookups.map(ModuleLookupTemplate).join('\n')}

@@ -133,10 +103,9 @@ return nullptr;

function translateReturnTypeToKind(
nullableTypeAnnotation ,
resolveAlias ,
) {
const [typeAnnotation] = unwrapNullable (
nullableTypeAnnotation,
);
function translateReturnTypeToKind(nullableTypeAnnotation, resolveAlias) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 1),
typeAnnotation = _unwrapNullable2[0];
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -151,52 +120,86 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

return 'NumberKind';
default:
(realTypeAnnotation.name );
throw new Error(
`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`,
);
realTypeAnnotation.name;
throw new Error(`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`);
}
case 'VoidTypeAnnotation':
return 'VoidKind';
case 'StringTypeAnnotation':
return 'StringKind';
case 'BooleanTypeAnnotation':
return 'BooleanKind';
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(`Unknown enum prop type for returning value, found: ${realTypeAnnotation.type}"`);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(`Unsupported union member returning value, found: ${realTypeAnnotation.memberType}"`);
}
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'DoubleTypeAnnotation':
return 'NumberKind';
case 'FloatTypeAnnotation':
return 'NumberKind';
case 'Int32TypeAnnotation':
return 'NumberKind';
case 'PromiseTypeAnnotation':
return 'PromiseKind';
case 'GenericObjectTypeAnnotation':
return 'ObjectKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'ArrayTypeAnnotation':
return 'ArrayKind';
default:
(realTypeAnnotation.type );
throw new Error(
`Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`,
);
realTypeAnnotation.type;
throw new Error(`Unknown prop type for returning value, found: ${realTypeAnnotation.type}"`);
}
}
function translateParamTypeToJniType(param, resolveAlias) {
const optional = param.optional,
nullableTypeAnnotation = param.typeAnnotation;
function translateParamTypeToJniType(
param ,
resolveAlias ,
) {
const {optional, typeAnnotation: nullableTypeAnnotation} = param;
const [
typeAnnotation,
nullable,
] = unwrapNullable (nullableTypeAnnotation);
const _unwrapNullable3 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2),
typeAnnotation = _unwrapNullable4[0],
nullable = _unwrapNullable4[1];
const isRequired = !optional && !nullable;
let realTypeAnnotation = typeAnnotation;
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -211,43 +214,79 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

return !isRequired ? 'Ljava/lang/Double;' : 'D';
default:
(realTypeAnnotation.name );
throw new Error(
`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`,
);
realTypeAnnotation.name;
throw new Error(`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`);
}
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
case 'BooleanTypeAnnotation':
return !isRequired ? 'Ljava/lang/Boolean;' : 'Z';
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(`Unknown enum prop type for method arg, found: ${realTypeAnnotation.type}"`);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/ReadableMap;';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(`Unsupported union prop value, found: ${realTypeAnnotation.memberType}"`);
}
case 'NumberTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'DoubleTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'FloatTypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'Int32TypeAnnotation':
return !isRequired ? 'Ljava/lang/Double;' : 'D';
case 'GenericObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/ReadableMap;';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/ReadableMap;';
case 'ArrayTypeAnnotation':
return 'Lcom/facebook/react/bridge/ReadableArray;';
case 'FunctionTypeAnnotation':
return 'Lcom/facebook/react/bridge/Callback;';
default:
(realTypeAnnotation.type );
throw new Error(
`Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`,
);
realTypeAnnotation.type;
throw new Error(`Unknown prop type for method arg, found: ${realTypeAnnotation.type}"`);
}
}
function translateReturnTypeToJniType(
nullableTypeAnnotation ,
resolveAlias ,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function translateReturnTypeToJniType(nullableTypeAnnotation, resolveAlias) {
const _unwrapNullable5 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable6 = _slicedToArray(_unwrapNullable5, 2),
typeAnnotation = _unwrapNullable6[0],
nullable = _unwrapNullable6[1];
let realTypeAnnotation = typeAnnotation;
if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -262,53 +301,91 @@ realTypeAnnotation = resolveAlias(realTypeAnnotation.name);

return nullable ? 'Ljava/lang/Double;' : 'D';
default:
(realTypeAnnotation.name );
throw new Error(
`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`,
);
realTypeAnnotation.name;
throw new Error(`Invalid ReservedFunctionValueTypeName name, got ${realTypeAnnotation.name}`);
}
case 'VoidTypeAnnotation':
return 'V';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
case 'BooleanTypeAnnotation':
return nullable ? 'Ljava/lang/Boolean;' : 'Z';
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(`Unknown enum prop type for method return type, found: ${realTypeAnnotation.type}"`);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableMap;';
case 'StringTypeAnnotation':
return 'Ljava/lang/String;';
default:
throw new Error(`Unsupported union member type, found: ${realTypeAnnotation.memberType}"`);
}
case 'NumberTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'DoubleTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'FloatTypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'Int32TypeAnnotation':
return nullable ? 'Ljava/lang/Double;' : 'D';
case 'PromiseTypeAnnotation':
return 'Lcom/facebook/react/bridge/Promise;';
case 'GenericObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableMap;';
case 'ObjectTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableMap;';
case 'ArrayTypeAnnotation':
return 'Lcom/facebook/react/bridge/WritableArray;';
default:
(realTypeAnnotation.type );
throw new Error(
`Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`,
);
realTypeAnnotation.type;
throw new Error(`Unknown prop type for method return type, found: ${realTypeAnnotation.type}"`);
}
}
function translateMethodTypeToJniSignature(
property ,
resolveAlias ,
) {
const {name, typeAnnotation} = property;
let [
{returnTypeAnnotation, params},
] = unwrapNullable (typeAnnotation);
function translateMethodTypeToJniSignature(property, resolveAlias) {
const name = property.name,
typeAnnotation = property.typeAnnotation;
let _unwrapNullable7 = unwrapNullable(typeAnnotation),
_unwrapNullable8 = _slicedToArray(_unwrapNullable7, 1),
_unwrapNullable8$ = _unwrapNullable8[0],
returnTypeAnnotation = _unwrapNullable8$.returnTypeAnnotation,
params = _unwrapNullable8$.params;
params = [...params];
let processedReturnTypeAnnotation = returnTypeAnnotation;
const isPromiseReturn = returnTypeAnnotation.type === 'PromiseTypeAnnotation';
if (isPromiseReturn) {
processedReturnTypeAnnotation = {
type: 'VoidTypeAnnotation',
type: 'VoidTypeAnnotation'
};

@@ -320,37 +397,21 @@ }

});
if (isPromiseReturn) {
// Additional promise arg for this case.
argsSignatureParts.push(
translateReturnTypeToJniType(returnTypeAnnotation, resolveAlias),
);
argsSignatureParts.push(translateReturnTypeToJniType(returnTypeAnnotation, resolveAlias));
}
const argsSignature = argsSignatureParts.join('');
const returnSignature =
name === 'getConstants'
? 'Ljava/util/Map;'
: translateReturnTypeToJniType(
processedReturnTypeAnnotation,
resolveAlias,
);
const returnSignature = name === 'getConstants' ? 'Ljava/util/Map;' : translateReturnTypeToJniType(processedReturnTypeAnnotation, resolveAlias);
return `(${argsSignature})${returnSignature}`;
}
function translateMethodForImplementation(
hasteModuleName ,
property ,
resolveAlias ,
) {
const [
propertyTypeAnnotation,
] = unwrapNullable (
property.typeAnnotation,
);
const {returnTypeAnnotation} = propertyTypeAnnotation;
function translateMethodForImplementation(hasteModuleName, property, resolveAlias) {
const _unwrapNullable9 = unwrapNullable(property.typeAnnotation),
_unwrapNullable10 = _slicedToArray(_unwrapNullable9, 1),
propertyTypeAnnotation = _unwrapNullable10[0];
if (
property.name === 'getConstants' &&
returnTypeAnnotation.type === 'ObjectTypeAnnotation' &&
returnTypeAnnotation.properties.length === 0
) {
const returnTypeAnnotation = propertyTypeAnnotation.returnTypeAnnotation;
if (property.name === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties.length === 0) {
return '';

@@ -363,3 +424,3 @@ }

jniSignature: translateMethodTypeToJniSignature(property, resolveAlias),
jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias),
jsReturnType: translateReturnTypeToKind(returnTypeAnnotation, resolveAlias)
});

@@ -369,100 +430,60 @@ }

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules).filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(module.excludedPlatforms != null && module.excludedPlatforms.includes('android'));
}).sort().map(hasteModuleName => {
const _nativeModules$hasteM = nativeModules[hasteModuleName],
aliases = _nativeModules$hasteM.aliases,
properties = _nativeModules$hasteM.spec.properties;
const resolveAlias = createAliasResolver(aliases);
const translatedMethods = properties.map(property => translateMethodForImplementation(hasteModuleName, property, resolveAlias)).join('\n\n');
return translatedMethods + '\n\n' + ModuleClassConstructorTemplate({
hasteModuleName,
methods: properties.map(({
name: propertyName,
typeAnnotation
}) => {
const _unwrapNullable11 = unwrapNullable(typeAnnotation),
_unwrapNullable12 = _slicedToArray(_unwrapNullable11, 1),
_unwrapNullable12$ = _unwrapNullable12[0],
returnTypeAnnotation = _unwrapNullable12$.returnTypeAnnotation,
params = _unwrapNullable12$.params;
const modules = Object.keys(nativeModules)
.filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(
module.excludedPlatforms != null &&
module.excludedPlatforms.includes('android')
);
})
.sort()
.map(hasteModuleName => {
const {
aliases,
spec: {properties},
} = nativeModules[hasteModuleName];
const resolveAlias = createAliasResolver(aliases);
if (propertyName === 'getConstants' && returnTypeAnnotation.type === 'ObjectTypeAnnotation' && returnTypeAnnotation.properties && returnTypeAnnotation.properties.length === 0) {
return null;
}
const translatedMethods = properties
.map(property =>
translateMethodForImplementation(
hasteModuleName,
property,
resolveAlias,
),
)
.join('\n\n');
return {
propertyName,
argCount: params.length
};
}).filter(Boolean)
});
}).join('\n'); // $FlowFixMe[missing-type-arg]
return (
translatedMethods +
'\n\n' +
ModuleClassConstructorTemplate({
hasteModuleName,
methods: properties
.map(({name: propertyName, typeAnnotation}) => {
const [
{returnTypeAnnotation, params},
] = unwrapNullable (
typeAnnotation,
);
const moduleLookups = Object.keys(nativeModules).filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(module.excludedPlatforms != null && module.excludedPlatforms.includes('android'));
}).sort((a, b) => {
const moduleA = nativeModules[a];
const moduleB = nativeModules[b];
const nameA = moduleA.moduleNames[0];
const nameB = moduleB.moduleNames[0];
if (
propertyName === 'getConstants' &&
returnTypeAnnotation.type === 'ObjectTypeAnnotation' &&
returnTypeAnnotation.properties &&
returnTypeAnnotation.properties.length === 0
) {
return null;
}
if (nameA < nameB) {
return -1;
} else if (nameA > nameB) {
return 1;
}
return {
propertyName,
argCount: params.length,
};
})
.filter(Boolean),
})
);
})
.join('\n');
// $FlowFixMe[missing-type-arg]
const moduleLookups = Object.keys(nativeModules)
.filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(
module.excludedPlatforms != null &&
module.excludedPlatforms.includes('android')
);
})
.sort((a, b) => {
const moduleA = nativeModules[a];
const moduleB = nativeModules[b];
const nameA = moduleA.moduleNames[0];
const nameB = moduleB.moduleNames[0];
if (nameA < nameB) {
return -1;
} else if (nameA > nameB) {
return 1;
}
return 0;
})
.flatMap (
(hasteModuleName ) => {
const {moduleNames} = nativeModules[hasteModuleName];
return moduleNames.map(moduleName => ({
moduleName,
hasteModuleName,
}));
},
);
return 0;
}).flatMap(hasteModuleName => {
const moduleNames = nativeModules[hasteModuleName].moduleNames;
return moduleNames.map(moduleName => ({
moduleName,
hasteModuleName
}));
});
const fileName = `${libraryName}-generated.cpp`;

@@ -473,6 +494,7 @@ const replacedTemplate = FileTemplate({

moduleLookups,
include: `"${libraryName}.h"`,
include: `"${libraryName}.h"`
});
return new Map([[`jni/${fileName}`, replacedTemplate]]);
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,14 +10,10 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const _require = require('./Utils'),
getModules = _require.getModules;
const {getModules} = require('./Utils');
const ModuleClassDeclarationTemplate = ({
hasteModuleName,
} ) => {
hasteModuleName
}) => {
return `/**

@@ -35,10 +31,10 @@ * JNI C++ class for module '${hasteModuleName}'

modules,
libraryName,
} ) => {
libraryName
}) => {
return `
/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -59,3 +55,4 @@ * ${'@'}generated by codegen project: GenerateModuleJniH.js

std::shared_ptr<TurboModule> ${libraryName}_ModuleProvider(const std::string moduleName, const JavaTurboModule::InitParams &params);
JSI_EXPORT
std::shared_ptr<TurboModule> ${libraryName}_ModuleProvider(const std::string &moduleName, const JavaTurboModule::InitParams &params);

@@ -65,7 +62,9 @@ } // namespace react

`;
};
}; // Note: this Android.mk template includes dependencies for both NativeModule and components.
// Note: this Android.mk template includes dependencies for both NativeModule and components.
const AndroidMkTemplate = ({libraryName} ) => {
return `# Copyright (c) Facebook, Inc. and its affiliates.
const AndroidMkTemplate = ({
libraryName
}) => {
return `# Copyright (c) Meta Platforms, Inc. and affiliates.
#

@@ -84,53 +83,106 @@ # This source code is licensed under the MIT license found in the

LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.cpp) $(wildcard $(LOCAL_PATH)/react/renderer/components/${libraryName}/*.cpp)
LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/,,$(LOCAL_SRC_FILES))
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/react/renderer/components/${libraryName}
LOCAL_SHARED_LIBRARIES := libglog libfolly_json libyoga libreact_nativemodule_core librrc_view libreact_render_core libreact_render_graphics libreact_debug libreact_render_debug
LOCAL_SHARED_LIBRARIES := libfbjni \
libfolly_runtime \
libglog \
libjsi \
libreact_codegen_rncore \
libreact_debug \
libreact_nativemodule_core \
libreact_render_core \
libreact_render_debug \
libreact_render_graphics \
libreact_render_imagemanager \
libreact_render_mapbuffer \
librrc_image \
librrc_view \
libturbomodulejsijni \
libyoga
LOCAL_STATIC_LIBRARIES := libjsi
LOCAL_CFLAGS := \\
-DLOG_TAG=\\"ReactNative\\"
LOCAL_CFLAGS += -fexceptions -frtti -std=c++14 -Wall
LOCAL_CFLAGS += -fexceptions -frtti -std=c++17 -Wall
include $(BUILD_SHARED_LIBRARY)
`;
}; // Note: this CMakeLists.txt template includes dependencies for both NativeModule and components.
const CMakeListsTemplate = ({
libraryName
}) => {
return `# 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.
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp react/renderer/components/${libraryName}/*.cpp)
add_library(
react_codegen_${libraryName}
SHARED
\${react_codegen_SRCS}
)
target_include_directories(react_codegen_${libraryName} PUBLIC . react/renderer/components/${libraryName})
target_link_libraries(
react_codegen_${libraryName}
fbjni
folly_runtime
glog
jsi
${libraryName !== 'rncore' ? 'react_codegen_rncore' : ''}
react_debug
react_nativemodule_core
react_render_core
react_render_debug
react_render_graphics
react_render_imagemanager
rrc_image
rrc_view
turbomodulejsijni
yoga
)
target_compile_options(
react_codegen_${libraryName}
PRIVATE
-DLOG_TAG=\\"ReactNative\\"
-fexceptions
-frtti
-std=c++17
-Wall
)
`;
};
module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull = false,
) {
generate(libraryName, schema, packageName, assumeNonnull = false) {
const nativeModules = getModules(schema);
const modules = Object.keys(nativeModules)
.filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(
module.excludedPlatforms != null &&
module.excludedPlatforms.includes('android')
);
})
.sort()
.map(hasteModuleName => ModuleClassDeclarationTemplate({hasteModuleName}))
.join('\n');
const modules = Object.keys(nativeModules).filter(hasteModuleName => {
const module = nativeModules[hasteModuleName];
return !(module.excludedPlatforms != null && module.excludedPlatforms.includes('android'));
}).sort().map(hasteModuleName => ModuleClassDeclarationTemplate({
hasteModuleName
})).join('\n');
const fileName = `${libraryName}.h`;
const replacedTemplate = HeaderFileTemplate({
modules: modules,
libraryName: libraryName.replace(/-/g, '_'),
libraryName: libraryName.replace(/-/g, '_')
});
return new Map([
[`jni/${fileName}`, replacedTemplate],
[
'jni/Android.mk',
AndroidMkTemplate({
libraryName: `${libraryName.toLowerCase()}`,
}),
],
]);
},
};
return new Map([[`jni/${fileName}`, replacedTemplate], ['jni/Android.mk', AndroidMkTemplate({
libraryName: libraryName
})], ['jni/CMakeLists.txt', CMakeListsTemplate({
libraryName: libraryName
})]]);
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,23 +10,27 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {getSafePropertyName, getNamespacedStructName} = require('../Utils');
const {capitalize} = require('../../../Utils');
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
const {unwrapNullable} = require('../../../../parsers/flow/modules/utils');
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('../Utils'),
getSafePropertyName = _require.getSafePropertyName,
getNamespacedStructName = _require.getNamespacedStructName;
const _require2 = require('../../../Utils'),
capitalize = _require2.capitalize;
const _require3 = require('../../../../parsers/parsers-commons'),
unwrapNullable = _require3.unwrapNullable;
const StructTemplate = ({
hasteModuleName,
structName,
builderInputProps,
}
) => `namespace JS {
builderInputProps
}) => `namespace JS {
namespace ${hasteModuleName} {

@@ -62,8 +66,4 @@ struct ${structName} {

structName,
properties,
}
) => `inline JS::${hasteModuleName}::${structName}::Builder::Builder(const Input i) : _factory(^{
properties
}) => `inline JS::${hasteModuleName}::${structName}::Builder::Builder(const Input i) : _factory(^{
NSMutableDictionary *d = [NSMutableDictionary new];

@@ -77,11 +77,12 @@ ${properties}

function toObjCType(
hasteModuleName ,
nullableTypeAnnotation ,
isOptional = false,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function toObjCType(hasteModuleName, nullableTypeAnnotation, isOptional = false) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
const isRequired = !nullable && !isOptional;
const wrapFollyOptional = (type ) => {
return isRequired ? type : `folly::Optional<${type}>`;
const wrapOptional = type => {
return isRequired ? type : `std::optional<${type}>`;
};

@@ -93,21 +94,42 @@

case 'RootTag':
return wrapFollyOptional('double');
return wrapOptional('double');
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`);
}
case 'StringTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'FloatTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'Int32TypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'DoubleTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'BooleanTypeAnnotation':
return wrapFollyOptional('bool');
return wrapOptional('bool');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapOptional('double');
case 'StringTypeAnnotation':
return 'NSString *';
default:
throw new Error(`Couldn't convert enum into ObjC type: ${typeAnnotation.type}"`);
}
case 'GenericObjectTypeAnnotation':
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable ';
case 'ArrayTypeAnnotation':

@@ -118,37 +140,25 @@ if (typeAnnotation.elementType == null) {

return wrapFollyOptional(
`std::vector<${toObjCType(
hasteModuleName,
typeAnnotation.elementType,
)}>`,
);
return wrapOptional(`std::vector<${toObjCType(hasteModuleName, typeAnnotation.elementType)}>`);
case 'TypeAliasTypeAnnotation':
const structName = capitalize(typeAnnotation.name);
const namespacedStructName = getNamespacedStructName(
hasteModuleName,
structName,
);
return wrapFollyOptional(`${namespacedStructName}::Builder`);
const namespacedStructName = getNamespacedStructName(hasteModuleName, structName);
return wrapOptional(`${namespacedStructName}::Builder`);
default:
(typeAnnotation.type );
throw new Error(
`Couldn't convert into ObjC type: ${typeAnnotation.type}"`,
);
typeAnnotation.type;
throw new Error(`Couldn't convert into ObjC type: ${typeAnnotation.type}"`);
}
}
function toObjCValue(
hasteModuleName ,
nullableTypeAnnotation ,
value ,
depth ,
isOptional = false,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function toObjCValue(hasteModuleName, nullableTypeAnnotation, value, depth, isOptional = false) {
const _unwrapNullable3 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2),
typeAnnotation = _unwrapNullable4[0],
nullable = _unwrapNullable4[1];
const isRequired = !nullable && !isOptional;
function wrapPrimitive(type ) {
return !isRequired
? `${value}.hasValue() ? @((${type})${value}.value()) : nil`
: `@(${value})`;
function wrapPrimitive(type) {
return !isRequired ? `${value}.has_value() ? @((${type})${value}.value()) : nil` : `@(${value})`;
}

@@ -161,24 +171,44 @@

return wrapPrimitive('double');
default:
(typeAnnotation.name );
throw new Error(
`Couldn't convert into ObjC type: ${typeAnnotation.type}"`,
);
typeAnnotation.name;
throw new Error(`Couldn't convert into ObjC type: ${typeAnnotation.type}"`);
}
case 'StringTypeAnnotation':
return value;
case 'NumberTypeAnnotation':
return wrapPrimitive('double');
case 'FloatTypeAnnotation':
return wrapPrimitive('double');
case 'Int32TypeAnnotation':
return wrapPrimitive('double');
case 'DoubleTypeAnnotation':
return wrapPrimitive('double');
case 'BooleanTypeAnnotation':
return wrapPrimitive('BOOL');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapPrimitive('double');
case 'StringTypeAnnotation':
return value;
default:
throw new Error(`Couldn't convert enum into ObjC value: ${typeAnnotation.type}"`);
}
case 'GenericObjectTypeAnnotation':
return value;
case 'ArrayTypeAnnotation':
const {elementType} = typeAnnotation;
const elementType = typeAnnotation.elementType;
if (elementType == null) {

@@ -190,84 +220,64 @@ return value;

const elementObjCType = toObjCType(hasteModuleName, elementType);
const elementObjCValue = toObjCValue(
hasteModuleName,
elementType,
localVarName,
depth + 1,
);
const elementObjCValue = toObjCValue(hasteModuleName, elementType, localVarName, depth + 1);
const RCTConvertVecToArray = transformer => {
return `RCTConvert${
!isRequired ? 'Optional' : ''
}VecToArray(${value}, ${transformer})`;
return `RCTConvert${!isRequired ? 'Optional' : ''}VecToArray(${value}, ${transformer})`;
};
return RCTConvertVecToArray(
`^id(${elementObjCType} ${localVarName}) { return ${elementObjCValue}; }`,
);
return RCTConvertVecToArray(`^id(${elementObjCType} ${localVarName}) { return ${elementObjCValue}; }`);
case 'TypeAliasTypeAnnotation':
return !isRequired
? `${value}.hasValue() ? ${value}.value().buildUnsafeRawValue() : nil`
: `${value}.buildUnsafeRawValue()`;
return !isRequired ? `${value}.has_value() ? ${value}.value().buildUnsafeRawValue() : nil` : `${value}.buildUnsafeRawValue()`;
default:
(typeAnnotation.type );
throw new Error(
`Couldn't convert into ObjC value: ${typeAnnotation.type}"`,
);
typeAnnotation.type;
throw new Error(`Couldn't convert into ObjC value: ${typeAnnotation.type}"`);
}
}
function serializeConstantsStruct(
hasteModuleName ,
struct ,
) {
function serializeConstantsStruct(hasteModuleName, struct) {
const declaration = StructTemplate({
hasteModuleName,
structName: struct.name,
builderInputProps: struct.properties
.map(property => {
const {typeAnnotation, optional} = property;
const safePropName = getSafePropertyName(property);
const objCType = toObjCType(hasteModuleName, typeAnnotation, optional);
builderInputProps: struct.properties.map(property => {
const typeAnnotation = property.typeAnnotation,
optional = property.optional;
const safePropName = getSafePropertyName(property);
const objCType = toObjCType(hasteModuleName, typeAnnotation, optional);
if (!optional) {
return `RCTRequired<${objCType}> ${safePropName};`;
}
if (!optional) {
return `RCTRequired<${objCType}> ${safePropName};`;
}
const space = ' '.repeat(objCType.endsWith('*') ? 0 : 1);
return `${objCType}${space}${safePropName};`;
})
.join('\n '),
const space = ' '.repeat(objCType.endsWith('*') ? 0 : 1);
return `${objCType}${space}${safePropName};`;
}).join('\n ')
});
const methods = MethodTemplate({
hasteModuleName,
structName: struct.name,
properties: struct.properties
.map(property => {
const {typeAnnotation, optional, name: propName} = property;
const safePropName = getSafePropertyName(property);
const objCValue = toObjCValue(
hasteModuleName,
typeAnnotation,
safePropName,
0,
optional,
);
properties: struct.properties.map(property => {
const typeAnnotation = property.typeAnnotation,
optional = property.optional,
propName = property.name;
const safePropName = getSafePropertyName(property);
const objCValue = toObjCValue(hasteModuleName, typeAnnotation, safePropName, 0, optional);
let varDecl = `auto ${safePropName} = i.${safePropName}`;
let varDecl = `auto ${safePropName} = i.${safePropName}`;
if (!optional) {
varDecl += '.get()';
}
if (!optional) {
varDecl += '.get()';
}
const assignment = `d[@"${propName}"] = ` + objCValue;
return ` ${varDecl};\n ${assignment};`;
})
.join('\n'),
const assignment = `d[@"${propName}"] = ` + objCValue;
return ` ${varDecl};\n ${assignment};`;
}).join('\n')
});
return {declaration, methods};
return {
declaration,
methods
};
}
module.exports = {
serializeConstantsStruct,
};
serializeConstantsStruct
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,23 +10,27 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {getSafePropertyName, getNamespacedStructName} = require('../Utils');
const {capitalize} = require('../../../Utils');
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
const {unwrapNullable} = require('../../../../parsers/flow/modules/utils');
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const _require = require('../Utils'),
getSafePropertyName = _require.getSafePropertyName,
getNamespacedStructName = _require.getNamespacedStructName;
const _require2 = require('../../../Utils'),
capitalize = _require2.capitalize;
const _require3 = require('../../../../parsers/parsers-commons'),
unwrapNullable = _require3.unwrapNullable;
const StructTemplate = ({
hasteModuleName,
structName,
structProperties,
}
) => `namespace JS {
structProperties
}) => `namespace JS {
namespace ${hasteModuleName} {

@@ -53,11 +57,4 @@ struct ${structName} {

propertyName,
safePropertyName,
}
) => `inline ${returnType}JS::${hasteModuleName}::${structName}::${safePropertyName}() const
safePropertyName
}) => `inline ${returnType}JS::${hasteModuleName}::${structName}::${safePropertyName}() const
{

@@ -68,11 +65,12 @@ id const p = _v[@"${propertyName}"];

function toObjCType(
hasteModuleName ,
nullableTypeAnnotation ,
isOptional = false,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function toObjCType(hasteModuleName, nullableTypeAnnotation, isOptional = false) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
const isRequired = !nullable && !isOptional;
const wrapFollyOptional = (type ) => {
return isRequired ? type : `folly::Optional<${type}>`;
const wrapOptional = type => {
return isRequired ? type : `std::optional<${type}>`;
};

@@ -84,21 +82,42 @@

case 'RootTag':
return wrapFollyOptional('double');
return wrapOptional('double');
default:
(typeAnnotation.name );
typeAnnotation.name;
throw new Error(`Unknown prop type, found: ${typeAnnotation.name}"`);
}
case 'StringTypeAnnotation':
return 'NSString *';
case 'NumberTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'FloatTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'Int32TypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'DoubleTypeAnnotation':
return wrapFollyOptional('double');
return wrapOptional('double');
case 'BooleanTypeAnnotation':
return wrapFollyOptional('bool');
return wrapOptional('bool');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapOptional('double');
case 'StringTypeAnnotation':
return 'NSString *';
default:
throw new Error(`Couldn't convert enum into ObjC type: ${typeAnnotation.type}"`);
}
case 'GenericObjectTypeAnnotation':
return isRequired ? 'id<NSObject> ' : 'id<NSObject> _Nullable';
case 'ArrayTypeAnnotation':

@@ -108,37 +127,27 @@ if (typeAnnotation.elementType == null) {

}
return wrapFollyOptional(
`facebook::react::LazyVector<${toObjCType(
hasteModuleName,
typeAnnotation.elementType,
)}>`,
);
return wrapOptional(`facebook::react::LazyVector<${toObjCType(hasteModuleName, typeAnnotation.elementType)}>`);
case 'TypeAliasTypeAnnotation':
const structName = capitalize(typeAnnotation.name);
const namespacedStructName = getNamespacedStructName(
hasteModuleName,
structName,
);
return wrapFollyOptional(namespacedStructName);
const namespacedStructName = getNamespacedStructName(hasteModuleName, structName);
return wrapOptional(namespacedStructName);
default:
(typeAnnotation.type );
throw new Error(
`Couldn't convert into ObjC type: ${typeAnnotation.type}"`,
);
typeAnnotation.type;
throw new Error(`Couldn't convert into ObjC type: ${typeAnnotation.type}"`);
}
}
function toObjCValue(
hasteModuleName ,
nullableTypeAnnotation ,
value ,
depth ,
isOptional = false,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function toObjCValue(hasteModuleName, nullableTypeAnnotation, value, depth, isOptional = false) {
const _unwrapNullable3 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2),
typeAnnotation = _unwrapNullable4[0],
nullable = _unwrapNullable4[1];
const isRequired = !nullable && !isOptional;
const RCTBridgingTo = (type , arg ) => {
const RCTBridgingTo = (type, arg) => {
const args = [value, arg].filter(Boolean).join(', ');
return isRequired
? `RCTBridgingTo${type}(${args})`
: `RCTBridgingToOptional${type}(${args})`;
return isRequired ? `RCTBridgingTo${type}(${args})` : `RCTBridgingToOptional${type}(${args})`;
};

@@ -151,24 +160,44 @@

return RCTBridgingTo('Double');
default:
(typeAnnotation.name );
throw new Error(
`Couldn't convert into ObjC type: ${typeAnnotation.type}"`,
);
typeAnnotation.name;
throw new Error(`Couldn't convert into ObjC type: ${typeAnnotation.type}"`);
}
case 'StringTypeAnnotation':
return RCTBridgingTo('String');
case 'NumberTypeAnnotation':
return RCTBridgingTo('Double');
case 'FloatTypeAnnotation':
return RCTBridgingTo('Double');
case 'Int32TypeAnnotation':
return RCTBridgingTo('Double');
case 'DoubleTypeAnnotation':
return RCTBridgingTo('Double');
case 'BooleanTypeAnnotation':
return RCTBridgingTo('Bool');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return RCTBridgingTo('Double');
case 'StringTypeAnnotation':
return RCTBridgingTo('String');
default:
throw new Error(`Couldn't convert enum into ObjC value: ${typeAnnotation.type}"`);
}
case 'GenericObjectTypeAnnotation':
return value;
case 'ArrayTypeAnnotation':
const {elementType} = typeAnnotation;
const elementType = typeAnnotation.elementType;
if (elementType == null) {

@@ -180,85 +209,55 @@ return value;

const elementObjCType = toObjCType(hasteModuleName, elementType);
const elementObjCValue = toObjCValue(
hasteModuleName,
elementType,
localVarName,
depth + 1,
);
const elementObjCValue = toObjCValue(hasteModuleName, elementType, localVarName, depth + 1);
return RCTBridgingTo('Vec', `^${elementObjCType}(id ${localVarName}) { return ${elementObjCValue}; }`);
return RCTBridgingTo(
'Vec',
`^${elementObjCType}(id ${localVarName}) { return ${elementObjCValue}; }`,
);
case 'TypeAliasTypeAnnotation':
const structName = capitalize(typeAnnotation.name);
const namespacedStructName = getNamespacedStructName(
hasteModuleName,
structName,
);
const namespacedStructName = getNamespacedStructName(hasteModuleName, structName);
return !isRequired ? `(${value} == nil ? std::nullopt : std::make_optional(${namespacedStructName}(${value})))` : `${namespacedStructName}(${value})`;
return !isRequired
? `(${value} == nil ? folly::none : folly::make_optional(${namespacedStructName}(${value})))`
: `${namespacedStructName}(${value})`;
default:
(typeAnnotation.type );
throw new Error(
`Couldn't convert into ObjC value: ${typeAnnotation.type}"`,
);
typeAnnotation.type;
throw new Error(`Couldn't convert into ObjC value: ${typeAnnotation.type}"`);
}
}
function serializeRegularStruct(
hasteModuleName ,
struct ,
) {
function serializeRegularStruct(hasteModuleName, struct) {
const declaration = StructTemplate({
hasteModuleName: hasteModuleName,
structName: struct.name,
structProperties: struct.properties
.map(property => {
const {typeAnnotation, optional} = property;
const safePropName = getSafePropertyName(property);
const returnType = toObjCType(
hasteModuleName,
typeAnnotation,
optional,
);
const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1);
return `${returnType}${padding}${safePropName}() const;`;
})
.join('\n '),
});
// $FlowFixMe[missing-type-arg]
const methods = struct.properties
.map (property => {
const {typeAnnotation, optional, name: propName} = property;
const safePropertyName = getSafePropertyName(property);
structProperties: struct.properties.map(property => {
const typeAnnotation = property.typeAnnotation,
optional = property.optional;
const safePropName = getSafePropertyName(property);
const returnType = toObjCType(hasteModuleName, typeAnnotation, optional);
const returnValue = toObjCValue(
hasteModuleName,
typeAnnotation,
'p',
0,
optional,
);
const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1);
return MethodTemplate({
hasteModuleName,
structName: struct.name,
returnType: returnType + padding,
returnValue: returnValue,
propertyName: propName,
safePropertyName,
});
})
.join('\n');
return `${returnType}${padding}${safePropName}() const;`;
}).join('\n ')
}); // $FlowFixMe[missing-type-arg]
return {methods, declaration};
const methods = struct.properties.map(property => {
const typeAnnotation = property.typeAnnotation,
optional = property.optional,
propName = property.name;
const safePropertyName = getSafePropertyName(property);
const returnType = toObjCType(hasteModuleName, typeAnnotation, optional);
const returnValue = toObjCValue(hasteModuleName, typeAnnotation, 'p', 0, optional);
const padding = ' '.repeat(returnType.endsWith('*') ? 0 : 1);
return MethodTemplate({
hasteModuleName,
structName: struct.name,
returnType: returnType + padding,
returnValue: returnValue,
propertyName: propName,
safePropertyName
});
}).join('\n');
return {
methods,
declaration
};
}
module.exports = {
serializeRegularStruct,
};
serializeRegularStruct
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,22 +10,15 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const _require = require('./serializeConstantsStruct'),
serializeConstantsStruct = _require.serializeConstantsStruct;
const {serializeConstantsStruct} = require('./serializeConstantsStruct');
const {serializeRegularStruct} = require('./serializeRegularStruct');
const _require2 = require('./serializeRegularStruct'),
serializeRegularStruct = _require2.serializeRegularStruct;
function serializeStruct(
hasteModuleName ,
struct ,
) {
function serializeStruct(hasteModuleName, struct) {
if (struct.context === 'REGULAR') {
return serializeRegularStruct(hasteModuleName, struct);
}
return serializeConstantsStruct(hasteModuleName, struct);

@@ -35,3 +28,3 @@ }

module.exports = {
serializeStruct,
};
serializeStruct
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,26 +10,25 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const _require = require('../Utils'),
createAliasResolver = _require.createAliasResolver,
getModules = _require.getModules;
const {createAliasResolver, getModules} = require('../Utils');
const _require2 = require('./StructCollector'),
StructCollector = _require2.StructCollector;
const {StructCollector} = require('./StructCollector');
const {serializeStruct} = require('./header/serializeStruct');
const {serializeMethod} = require('./serializeMethod');
const {serializeModuleSource} = require('./source/serializeModule');
const _require3 = require('./header/serializeStruct'),
serializeStruct = _require3.serializeStruct;
const _require4 = require('./serializeMethod'),
serializeMethod = _require4.serializeMethod;
const _require5 = require('./source/serializeModule'),
serializeModuleSource = _require5.serializeModuleSource;
const ModuleDeclarationTemplate = ({
hasteModuleName,
structDeclarations,
protocolMethods,
}
) => `${structDeclarations}
protocolMethods
}) => `${structDeclarations}
@protocol ${hasteModuleName}Spec <RCTBridgeModule, RCTTurboModule>

@@ -55,13 +54,8 @@

structInlineMethods,
assumeNonnull,
}
) =>
`/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
assumeNonnull
}) => `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -86,23 +80,15 @@ * ${'@'}generated by codegen project: GenerateModuleObjCpp

#import <ReactCommon/RCTTurboModule.h>
#import <folly/Optional.h>
#import <optional>
#import <vector>
` +
(assumeNonnull ? '\nNS_ASSUME_NONNULL_BEGIN\n' : '') +
moduleDeclarations +
'\n' +
structInlineMethods +
(assumeNonnull ? '\nNS_ASSUME_NONNULL_END\n' : '\n');
` + (assumeNonnull ? '\nNS_ASSUME_NONNULL_BEGIN\n' : '') + moduleDeclarations + '\n' + structInlineMethods + (assumeNonnull ? '\nNS_ASSUME_NONNULL_END\n' : '\n');
const SourceFileTemplate = ({
headerFileName,
moduleImplementations,
}
) => `/**
* ${'C'}opyright (c) Facebook, Inc. and its affiliates.
moduleImplementations
}) => `/**
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
* Do not edit this file as changes may cause incorrect behavior and will be lost
* once the code is regenerated.
*

@@ -122,39 +108,26 @@ * ${'@'}generated by codegen project: GenerateModuleObjCpp

module.exports = {
generate(
libraryName ,
schema ,
packageName ,
assumeNonnull ,
) {
generate(libraryName, schema, packageName, assumeNonnull) {
const nativeModules = getModules(schema);
const moduleDeclarations = [];
const structInlineMethods = [];
const moduleImplementations = [];
const hasteModuleNames = Object.keys(nativeModules).sort();
const moduleDeclarations = [];
const structInlineMethods = [];
const moduleImplementations = [];
for (const hasteModuleName of hasteModuleNames) {
const _nativeModules$hasteM = nativeModules[hasteModuleName],
aliases = _nativeModules$hasteM.aliases,
excludedPlatforms = _nativeModules$hasteM.excludedPlatforms,
properties = _nativeModules$hasteM.spec.properties;
const hasteModuleNames = Object.keys(nativeModules).sort();
for (const hasteModuleName of hasteModuleNames) {
const {
aliases,
excludedPlatforms,
spec: {properties},
} = nativeModules[hasteModuleName];
if (excludedPlatforms != null && excludedPlatforms.includes('iOS')) {
continue;
}
const resolveAlias = createAliasResolver(aliases);
const structCollector = new StructCollector();
const methodSerializations = [];
const methodSerializations = [];
const serializeProperty = property => {
methodSerializations.push(
...serializeMethod(
hasteModuleName,
property,
structCollector,
resolveAlias,
),
);
methodSerializations.push(...serializeMethod(hasteModuleName, property, structCollector, resolveAlias));
};
/**

@@ -164,9 +137,6 @@ * Note: As we serialize NativeModule methods, we insert structs into

*/
properties
.filter(property => property.name !== 'getConstants')
.forEach(serializeProperty);
properties
.filter(property => property.name === 'getConstants')
.forEach(serializeProperty);
properties.filter(property => property.name !== 'getConstants').forEach(serializeProperty);
properties.filter(property => property.name === 'getConstants').forEach(serializeProperty);
const generatedStructs = structCollector.getAllStructs();

@@ -177,3 +147,6 @@ const structStrs = [];

for (const struct of generatedStructs) {
const {methods, declaration} = serializeStruct(hasteModuleName, struct);
const _serializeStruct = serializeStruct(hasteModuleName, struct),
methods = _serializeStruct.methods,
declaration = _serializeStruct.declaration;
structStrs.push(declaration);

@@ -183,23 +156,13 @@ methodStrs.push(methods);

moduleDeclarations.push(
ModuleDeclarationTemplate({
hasteModuleName: hasteModuleName,
structDeclarations: structStrs.join('\n'),
protocolMethods: methodSerializations
.map(({protocolMethod}) => protocolMethod)
.join('\n'),
}),
);
moduleDeclarations.push(ModuleDeclarationTemplate({
hasteModuleName: hasteModuleName,
structDeclarations: structStrs.join('\n'),
protocolMethods: methodSerializations.map(({
protocolMethod
}) => protocolMethod).join('\n')
}));
structInlineMethods.push(methodStrs.join('\n'));
moduleImplementations.push(
serializeModuleSource(
hasteModuleName,
generatedStructs,
methodSerializations.filter(
({selector}) => selector !== '@selector(constantsToExport)',
),
),
);
moduleImplementations.push(serializeModuleSource(hasteModuleName, generatedStructs, methodSerializations.filter(({
selector
}) => selector !== '@selector(constantsToExport)')));
}

@@ -211,16 +174,12 @@

structInlineMethods: structInlineMethods.join('\n'),
assumeNonnull,
assumeNonnull
});
const sourceFileName = `${libraryName}-generated.mm`;
const sourceFile = SourceFileTemplate({
headerFileName,
moduleImplementations: moduleImplementations.join('\n'),
moduleImplementations: moduleImplementations.join('\n')
});
return new Map([[headerFileName, headerFile], [sourceFileName, sourceFile]]);
}
return new Map([
[headerFileName, headerFile],
[sourceFileName, sourceFile],
]);
},
};
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,136 +10,100 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
const invariant = require('invariant');
const {StructCollector} = require('./StructCollector');
const {getNamespacedStructName} = require('./Utils');
const {capitalize} = require('../../Utils');
const {
wrapNullable,
unwrapNullable,
} = require('../../../parsers/flow/modules/utils');
const _require = require('./Utils'),
getNamespacedStructName = _require.getNamespacedStructName;
const _require2 = require('../../Utils'),
capitalize = _require2.capitalize;
const _require3 = require('../../../parsers/parsers-commons'),
wrapNullable = _require3.wrapNullable,
unwrapNullable = _require3.unwrapNullable;
const ProtocolMethodTemplate = ({
returnObjCType,
methodName,
params,
}
) => `- (${returnObjCType})${methodName}${params};`;
params
}) => `- (${returnObjCType})${methodName}${params};`;
function serializeMethod(hasteModuleName, property, structCollector, resolveAlias) {
const methodName = property.name,
nullableTypeAnnotation = property.typeAnnotation;
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 1),
propertyTypeAnnotation = _unwrapNullable2[0];
const params = propertyTypeAnnotation.params;
function serializeMethod(
hasteModuleName ,
property ,
structCollector ,
resolveAlias ,
) {
const {name: methodName, typeAnnotation: nullableTypeAnnotation} = property;
const [propertyTypeAnnotation] = unwrapNullable(nullableTypeAnnotation);
const {params} = propertyTypeAnnotation;
if (methodName === 'getConstants') {
return serializeConstantsProtocolMethods(
hasteModuleName,
property,
structCollector,
resolveAlias,
);
return serializeConstantsProtocolMethods(hasteModuleName, property, structCollector, resolveAlias);
}
const methodParams = [];
const structParamRecords = [];
const methodParams = [];
const structParamRecords = [];
params.forEach((param, index) => {
const structName = getParamStructName(methodName, param);
const {objCType, isStruct} = getParamObjCType(
hasteModuleName,
methodName,
param,
structName,
structCollector,
resolveAlias,
);
methodParams.push({paramName: param.name, objCType});
const _getParamObjCType = getParamObjCType(hasteModuleName, methodName, param, structName, structCollector, resolveAlias),
objCType = _getParamObjCType.objCType,
isStruct = _getParamObjCType.isStruct;
methodParams.push({
paramName: param.name,
objCType
});
if (isStruct) {
structParamRecords.push({paramIndex: index, structName});
structParamRecords.push({
paramIndex: index,
structName
});
}
});
// Unwrap returnTypeAnnotation, so we check if the return type is Promise
}); // Unwrap returnTypeAnnotation, so we check if the return type is Promise
// TODO(T76719514): Disallow nullable PromiseTypeAnnotations
const [returnTypeAnnotation] = unwrapNullable(
propertyTypeAnnotation.returnTypeAnnotation,
);
const _unwrapNullable3 = unwrapNullable(propertyTypeAnnotation.returnTypeAnnotation),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 1),
returnTypeAnnotation = _unwrapNullable4[0];
if (returnTypeAnnotation.type === 'PromiseTypeAnnotation') {
methodParams.push(
{paramName: 'resolve', objCType: 'RCTPromiseResolveBlock'},
{paramName: 'reject', objCType: 'RCTPromiseRejectBlock'},
);
methodParams.push({
paramName: 'resolve',
objCType: 'RCTPromiseResolveBlock'
}, {
paramName: 'reject',
objCType: 'RCTPromiseRejectBlock'
});
}
/**
* Build Protocol Method
**/
const returnObjCType = getReturnObjCType(
methodName,
propertyTypeAnnotation.returnTypeAnnotation,
);
const paddingMax = `- (${returnObjCType})${methodName}`.length;
const objCParams = methodParams.reduce(
($objCParams, {objCType, paramName}, i) => {
const rhs = `(${objCType})${paramName}`;
const padding = ' '.repeat(Math.max(0, paddingMax - paramName.length));
return i === 0
? `:${rhs}`
: `${$objCParams}\n${padding}${paramName}:${rhs}`;
},
'',
);
const returnObjCType = getReturnObjCType(methodName, propertyTypeAnnotation.returnTypeAnnotation);
const paddingMax = `- (${returnObjCType})${methodName}`.length;
const objCParams = methodParams.reduce(($objCParams, {
objCType,
paramName
}, i) => {
const rhs = `(${objCType})${paramName}`;
const padding = ' '.repeat(Math.max(0, paddingMax - paramName.length));
return i === 0 ? `:${rhs}` : `${$objCParams}\n${padding}${paramName}:${rhs}`;
}, '');
const protocolMethod = ProtocolMethodTemplate({
methodName,
returnObjCType,
params: objCParams,
params: objCParams
});
/**

@@ -149,29 +113,28 @@ * Build ObjC Selector

// $FlowFixMe[missing-type-arg]
const selector = methodParams
.map (({paramName}) => paramName)
.reduce(($selector, paramName, i) => {
return i === 0 ? `${$selector}:` : `${$selector}${paramName}:`;
}, methodName);
const selector = methodParams.map(({
paramName
}) => paramName).reduce(($selector, paramName, i) => {
return i === 0 ? `${$selector}:` : `${$selector}${paramName}:`;
}, methodName);
/**
* Build JS Return type
*/
const returnJSType = getReturnJSType(methodName, returnTypeAnnotation);
return [
{
methodName,
protocolMethod,
selector: `@selector(${selector})`,
structParamRecords,
returnJSType,
argCount: params.length,
},
];
return [{
methodName,
protocolMethod,
selector: `@selector(${selector})`,
structParamRecords,
returnJSType,
argCount: params.length
}];
}
function getParamStructName(methodName, param) {
const _unwrapNullable5 = unwrapNullable(param.typeAnnotation),
_unwrapNullable6 = _slicedToArray(_unwrapNullable5, 1),
typeAnnotation = _unwrapNullable6[0];
function getParamStructName(methodName , param ) {
const [typeAnnotation] = unwrapNullable(param.typeAnnotation);
if (typeAnnotation.type === 'TypeAliasTypeAnnotation') {

@@ -184,72 +147,65 @@ return typeAnnotation.name;

function getParamObjCType(
hasteModuleName ,
methodName ,
param ,
structName ,
structCollector ,
resolveAlias ,
) {
const {name: paramName, typeAnnotation: nullableTypeAnnotation} = param;
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function getParamObjCType(hasteModuleName, methodName, param, structName, structCollector, resolveAlias) {
const paramName = param.name,
nullableTypeAnnotation = param.typeAnnotation;
const _unwrapNullable7 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable8 = _slicedToArray(_unwrapNullable7, 2),
typeAnnotation = _unwrapNullable8[0],
nullable = _unwrapNullable8[1];
const notRequired = param.optional || nullable;
function wrapIntoNullableIfNeeded(generatedType ) {
function wrapIntoNullableIfNeeded(generatedType) {
return nullable ? `${generatedType} _Nullable` : generatedType;
}
const isStruct = (objCType ) => ({
const isStruct = objCType => ({
isStruct: true,
objCType,
objCType
});
const notStruct = (objCType ) => ({
const notStruct = objCType => ({
isStruct: false,
objCType,
});
objCType
}); // Handle types that can only be in parameters
// Handle types that can only be in parameters
switch (typeAnnotation.type) {
case 'FunctionTypeAnnotation': {
return notStruct('RCTResponseSenderBlock');
}
case 'ArrayTypeAnnotation': {
/**
* Array in params always codegen NSArray *
*
* TODO(T73933406): Support codegen for Arrays of structs and primitives
*
* For example:
* Array<number> => NSArray<NSNumber *>
* type Animal = {};
* Array<Animal> => NSArray<JS::NativeSampleTurboModule::Animal *>, etc.
*/
return notStruct(wrapIntoNullableIfNeeded('NSArray *'));
}
case 'FunctionTypeAnnotation':
{
return notStruct('RCTResponseSenderBlock');
}
case 'ArrayTypeAnnotation':
{
/**
* Array in params always codegen NSArray *
*
* TODO(T73933406): Support codegen for Arrays of structs and primitives
*
* For example:
* Array<number> => NSArray<NSNumber *>
* type Animal = {};
* Array<Animal> => NSArray<JS::NativeSampleTurboModule::Animal *>, etc.
*/
return notStruct(wrapIntoNullableIfNeeded('NSArray *'));
}
}
const [structTypeAnnotation] = unwrapNullable(
structCollector.process(
structName,
'REGULAR',
resolveAlias,
wrapNullable(nullable, typeAnnotation),
),
);
const _unwrapNullable9 = unwrapNullable(structCollector.process(structName, 'REGULAR', resolveAlias, wrapNullable(nullable, typeAnnotation))),
_unwrapNullable10 = _slicedToArray(_unwrapNullable9, 1),
structTypeAnnotation = _unwrapNullable10[0];
invariant(
structTypeAnnotation.type !== 'ArrayTypeAnnotation',
'ArrayTypeAnnotations should have been processed earlier',
);
invariant(structTypeAnnotation.type !== 'ArrayTypeAnnotation', 'ArrayTypeAnnotations should have been processed earlier');
switch (structTypeAnnotation.type) {
case 'TypeAliasTypeAnnotation': {
/**
* TODO(T73943261): Support nullable object literals and aliases?
*/
return isStruct(
getNamespacedStructName(hasteModuleName, structTypeAnnotation.name) +
' &',
);
}
case 'TypeAliasTypeAnnotation':
{
/**
* TODO(T73943261): Support nullable object literals and aliases?
*/
return isStruct(getNamespacedStructName(hasteModuleName, structTypeAnnotation.name) + ' &');
}
case 'ReservedTypeAnnotation':

@@ -259,37 +215,54 @@ switch (structTypeAnnotation.name) {

return notStruct(notRequired ? 'NSNumber *' : 'double');
default:
(structTypeAnnotation.name );
throw new Error(
`Unsupported type for param "${paramName}" in ${methodName}. Found: ${structTypeAnnotation.type}`,
);
structTypeAnnotation.name;
throw new Error(`Unsupported type for param "${paramName}" in ${methodName}. Found: ${structTypeAnnotation.type}`);
}
case 'StringTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSString *'));
case 'NumberTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
case 'FloatTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
case 'DoubleTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
case 'Int32TypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
case 'BooleanTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'BOOL');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return notStruct(notRequired ? 'NSNumber *' : 'double');
case 'StringTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSString *'));
default:
throw new Error(`Unsupported enum type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`);
}
case 'GenericObjectTypeAnnotation':
return notStruct(wrapIntoNullableIfNeeded('NSDictionary *'));
default:
(structTypeAnnotation.type );
throw new Error(
`Unsupported type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`,
);
structTypeAnnotation.type;
throw new Error(`Unsupported type for param "${paramName}" in ${methodName}. Found: ${typeAnnotation.type}`);
}
}
function getReturnObjCType(
methodName ,
nullableTypeAnnotation ,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
function getReturnObjCType(methodName, nullableTypeAnnotation) {
const _unwrapNullable11 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable12 = _slicedToArray(_unwrapNullable11, 2),
typeAnnotation = _unwrapNullable12[0],
nullable = _unwrapNullable12[1];
function wrapIntoNullableIfNeeded(generatedType ) {
function wrapIntoNullableIfNeeded(generatedType) {
return nullable ? `${generatedType} _Nullable` : generatedType;

@@ -301,8 +274,12 @@ }

return 'void';
case 'PromiseTypeAnnotation':
return 'void';
case 'ObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
case 'TypeAliasTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
case 'ArrayTypeAnnotation':

@@ -313,8 +290,4 @@ if (typeAnnotation.elementType == null) {

return wrapIntoNullableIfNeeded(
`NSArray<${getReturnObjCType(
methodName,
typeAnnotation.elementType,
)}> *`,
);
return wrapIntoNullableIfNeeded(`NSArray<${getReturnObjCType(methodName, typeAnnotation.elementType)}> *`);
case 'ReservedTypeAnnotation':

@@ -324,8 +297,8 @@ switch (typeAnnotation.name) {

return wrapIntoNullableIfNeeded('NSNumber *');
default:
(typeAnnotation.name );
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.name}`,
);
typeAnnotation.name;
throw new Error(`Unsupported return type for ${methodName}. Found: ${typeAnnotation.name}`);
}
case 'StringTypeAnnotation':

@@ -335,80 +308,147 @@ // TODO: Can NSString * returns not be _Nullable?

return wrapIntoNullableIfNeeded('NSString *');
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'FloatTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'DoubleTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'Int32TypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'BooleanTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'StringTypeAnnotation':
return wrapIntoNullableIfNeeded('NSString *');
default:
throw new Error(`Unsupported enum return type for ${methodName}. Found: ${typeAnnotation.type}`);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return wrapIntoNullableIfNeeded('NSNumber *');
case 'ObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
case 'StringTypeAnnotation':
// TODO: Can NSString * returns not be _Nullable?
// In the legacy codegen, we don't surround NSSTring * with _Nullable
return wrapIntoNullableIfNeeded('NSString *');
default:
throw new Error(`Unsupported union return type for ${methodName}, found: ${typeAnnotation.memberType}"`);
}
case 'GenericObjectTypeAnnotation':
return wrapIntoNullableIfNeeded('NSDictionary *');
default:
(typeAnnotation.type );
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
typeAnnotation.type;
throw new Error(`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`);
}
}
function getReturnJSType(
methodName ,
nullableTypeAnnotation ,
) {
const [typeAnnotation] = unwrapNullable(nullableTypeAnnotation);
function getReturnJSType(methodName, nullableTypeAnnotation) {
const _unwrapNullable13 = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable14 = _slicedToArray(_unwrapNullable13, 1),
typeAnnotation = _unwrapNullable14[0];
switch (typeAnnotation.type) {
case 'VoidTypeAnnotation':
return 'VoidKind';
case 'PromiseTypeAnnotation':
return 'PromiseKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'TypeAliasTypeAnnotation':
return 'ObjectKind';
case 'ArrayTypeAnnotation':
return 'ArrayKind';
case 'ReservedTypeAnnotation':
return 'NumberKind';
case 'StringTypeAnnotation':
return 'StringKind';
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'FloatTypeAnnotation':
return 'NumberKind';
case 'DoubleTypeAnnotation':
return 'NumberKind';
case 'Int32TypeAnnotation':
return 'NumberKind';
case 'BooleanTypeAnnotation':
return 'BooleanKind';
case 'GenericObjectTypeAnnotation':
return 'ObjectKind';
case 'EnumDeclaration':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`);
}
case 'UnionTypeAnnotation':
switch (typeAnnotation.memberType) {
case 'NumberTypeAnnotation':
return 'NumberKind';
case 'ObjectTypeAnnotation':
return 'ObjectKind';
case 'StringTypeAnnotation':
return 'StringKind';
default:
throw new Error(`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`);
}
default:
(typeAnnotation.type );
throw new Error(
`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`,
);
typeAnnotation.type;
throw new Error(`Unsupported return type for ${methodName}. Found: ${typeAnnotation.type}`);
}
}
function serializeConstantsProtocolMethods(
hasteModuleName ,
property ,
structCollector ,
resolveAlias ,
) {
const [propertyTypeAnnotation] = unwrapNullable(property.typeAnnotation);
function serializeConstantsProtocolMethods(hasteModuleName, property, structCollector, resolveAlias) {
const _unwrapNullable15 = unwrapNullable(property.typeAnnotation),
_unwrapNullable16 = _slicedToArray(_unwrapNullable15, 1),
propertyTypeAnnotation = _unwrapNullable16[0];
if (propertyTypeAnnotation.params.length !== 0) {
throw new Error(
`${hasteModuleName}.getConstants() may only accept 0 arguments.`,
);
throw new Error(`${hasteModuleName}.getConstants() may only accept 0 arguments.`);
}
const {returnTypeAnnotation} = propertyTypeAnnotation;
const returnTypeAnnotation = propertyTypeAnnotation.returnTypeAnnotation;
if (returnTypeAnnotation.type !== 'ObjectTypeAnnotation') {
throw new Error(
`${hasteModuleName}.getConstants() may only return an object literal: {...}.`,
);
throw new Error(`${hasteModuleName}.getConstants() may only return an object literal: {...}.`);
}

@@ -420,39 +460,25 @@

const realTypeAnnotation = structCollector.process(
'Constants',
'CONSTANTS',
resolveAlias,
returnTypeAnnotation,
);
const realTypeAnnotation = structCollector.process('Constants', 'CONSTANTS', resolveAlias, returnTypeAnnotation);
invariant(realTypeAnnotation.type === 'TypeAliasTypeAnnotation', "Unable to generate C++ struct from module's getConstants() method return type.");
const returnObjCType = `facebook::react::ModuleConstants<JS::${hasteModuleName}::Constants::Builder>`; // $FlowFixMe[missing-type-arg]
invariant(
realTypeAnnotation.type === 'TypeAliasTypeAnnotation',
"Unable to generate C++ struct from module's getConstants() method return type.",
);
const returnObjCType = `facebook::react::ModuleConstants<JS::${hasteModuleName}::Constants::Builder>`;
// $FlowFixMe[missing-type-arg]
return ['constantsToExport', 'getConstants'].map (
methodName => {
const protocolMethod = ProtocolMethodTemplate({
methodName,
returnObjCType,
params: '',
});
return {
methodName,
protocolMethod,
returnJSType: 'ObjectKind',
selector: `@selector(${methodName})`,
structParamRecords: [],
argCount: 0,
};
},
);
return ['constantsToExport', 'getConstants'].map(methodName => {
const protocolMethod = ProtocolMethodTemplate({
methodName,
returnObjCType,
params: ''
});
return {
methodName,
protocolMethod,
returnJSType: 'ObjectKind',
selector: `@selector(${methodName})`,
structParamRecords: [],
argCount: 0
};
});
}
module.exports = {
serializeMethod,
};
serializeMethod
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,49 +10,33 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const ModuleTemplate = ({
hasteModuleName,
structs,
methodSerializationOutputs,
}
) => `${structs
.map(struct =>
RCTCxxConvertCategoryTemplate({hasteModuleName, structName: struct.name}),
)
.join('\n')}
methodSerializationOutputs
}) => `${structs.map(struct => RCTCxxConvertCategoryTemplate({
hasteModuleName,
structName: struct.name
})).join('\n')}
namespace facebook {
namespace react {
${methodSerializationOutputs
.map(serializedMethodParts =>
InlineHostFunctionTemplate({
hasteModuleName,
methodName: serializedMethodParts.methodName,
returnJSType: serializedMethodParts.returnJSType,
selector: serializedMethodParts.selector,
}),
)
.join('\n')}
${methodSerializationOutputs.map(serializedMethodParts => InlineHostFunctionTemplate({
hasteModuleName,
methodName: serializedMethodParts.methodName,
returnJSType: serializedMethodParts.returnJSType,
selector: serializedMethodParts.selector
})).join('\n')}
${hasteModuleName}SpecJSI::${hasteModuleName}SpecJSI(const ObjCTurboModule::InitParams &params)
: ObjCTurboModule(params) {
${methodSerializationOutputs
.map(({methodName, structParamRecords, argCount}) =>
MethodMapEntryTemplate({
hasteModuleName,
methodName,
structParamRecords,
argCount,
}),
)
.join('\n' + ' '.repeat(8))}
${methodSerializationOutputs.map(({
methodName,
structParamRecords,
argCount
}) => MethodMapEntryTemplate({
hasteModuleName,
methodName,
structParamRecords,
argCount
})).join('\n' + ' '.repeat(8))}
}

@@ -64,7 +48,4 @@ } // namespace react

hasteModuleName,
structName,
}
) => `@implementation RCTCxxConvert (${hasteModuleName}_${structName})
structName
}) => `@implementation RCTCxxConvert (${hasteModuleName}_${structName})
+ (RCTManagedPointer *)JS_${hasteModuleName}_${structName}:(id)json

@@ -80,9 +61,4 @@ {

returnJSType,
selector,
}
) => `
selector
}) => `
static facebook::jsi::Value __hostFunction_${hasteModuleName}SpecJSI_${methodName}(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {

@@ -96,25 +72,19 @@ return static_cast<ObjCTurboModule&>(turboModule).invokeObjCMethod(rt, ${returnJSType}, "${methodName}", ${selector}, args, count);

structParamRecords,
argCount,
}
) => `
argCount
}) => `
methodMap_["${methodName}"] = MethodMetadata {${argCount}, __hostFunction_${hasteModuleName}SpecJSI_${methodName}};
${structParamRecords
.map(({paramIndex, structName}) => {
return `setMethodArgConversionSelector(@"${methodName}", ${paramIndex}, @"JS_${hasteModuleName}_${structName}:");`;
})
.join('\n' + ' '.repeat(8))}`;
${structParamRecords.map(({
paramIndex,
structName
}) => {
return `setMethodArgConversionSelector(@"${methodName}", ${paramIndex}, @"JS_${hasteModuleName}_${structName}:");`;
}).join('\n' + ' '.repeat(8))}`;
function serializeModuleSource(
hasteModuleName ,
structs ,
methodSerializationOutputs ,
) {
function serializeModuleSource(hasteModuleName, structs, methodSerializationOutputs) {
return ModuleTemplate({
hasteModuleName,
structs: structs.filter(({context}) => context !== 'CONSTANTS'),
methodSerializationOutputs,
structs: structs.filter(({
context
}) => context !== 'CONSTANTS'),
methodSerializationOutputs
});

@@ -124,3 +94,3 @@ }

module.exports = {
serializeModuleSource,
};
serializeModuleSource
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,158 +10,101 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const {capitalize} = require('../../Utils');
const {
unwrapNullable,
wrapNullable,
} = require('../../../parsers/flow/modules/utils');
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const _require = require('../../Utils'),
capitalize = _require.capitalize;
const _require2 = require('../../../parsers/parsers-commons'),
unwrapNullable = _require2.unwrapNullable,
wrapNullable = _require2.wrapNullable;
class StructCollector {
_structs = new Map();
constructor() {
_defineProperty(this, "_structs", new Map());
}
process(
structName ,
structContext ,
resolveAlias ,
nullableTypeAnnotation ,
) {
const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation);
process(structName, structContext, resolveAlias, nullableTypeAnnotation) {
const _unwrapNullable = unwrapNullable(nullableTypeAnnotation),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
typeAnnotation = _unwrapNullable2[0],
nullable = _unwrapNullable2[1];
switch (typeAnnotation.type) {
case 'ObjectTypeAnnotation': {
this._insertStruct(
structName,
structContext,
resolveAlias,
typeAnnotation,
);
return wrapNullable(nullable, {
type: 'TypeAliasTypeAnnotation',
name: structName,
});
}
case 'ArrayTypeAnnotation': {
if (typeAnnotation.elementType == null) {
case 'ObjectTypeAnnotation':
{
this._insertStruct(structName, structContext, resolveAlias, typeAnnotation);
return wrapNullable(nullable, {
type: 'TypeAliasTypeAnnotation',
name: structName
});
}
case 'ArrayTypeAnnotation':
{
if (typeAnnotation.elementType == null) {
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation'
});
}
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
elementType: this.process(structName + 'Element', structContext, resolveAlias, typeAnnotation.elementType)
});
}
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
elementType: this.process(
structName + 'Element',
structContext,
resolveAlias,
typeAnnotation.elementType,
),
});
}
case 'TypeAliasTypeAnnotation': {
this._insertAlias(typeAnnotation.name, structContext, resolveAlias);
case 'TypeAliasTypeAnnotation':
{
this._insertAlias(typeAnnotation.name, structContext, resolveAlias);
return wrapNullable(nullable, typeAnnotation);
}
case 'EnumDeclaration':
return wrapNullable(nullable, typeAnnotation);
}
default: {
return wrapNullable(nullable, typeAnnotation);
}
case 'MixedTypeAnnotation':
throw new Error('Mixed types are unsupported in structs');
case 'UnionTypeAnnotation':
throw new Error('Union types are unsupported in structs');
default:
{
return wrapNullable(nullable, typeAnnotation);
}
}
}
_insertAlias(
aliasName ,
structContext ,
resolveAlias ,
) {
_insertAlias(aliasName, structContext, resolveAlias) {
const usedStruct = this._structs.get(aliasName);
if (usedStruct == null) {
this._insertStruct(
aliasName,
structContext,
resolveAlias,
resolveAlias(aliasName),
);
this._insertStruct(aliasName, structContext, resolveAlias, resolveAlias(aliasName));
} else if (usedStruct.context !== structContext) {
throw new Error(
`Tried to use alias '${aliasName}' in a getConstants() return type and inside a regular struct.`,
);
throw new Error(`Tried to use alias '${aliasName}' in a getConstants() return type and inside a regular struct.`);
}
}
_insertStruct(
structName ,
structContext ,
resolveAlias ,
objectTypeAnnotation ,
) {
_insertStruct(structName, structContext, resolveAlias, objectTypeAnnotation) {
// $FlowFixMe[missing-type-arg]
const properties = objectTypeAnnotation.properties.map
(property => {
const properties = objectTypeAnnotation.properties.map(property => {
const propertyStructName = structName + capitalize(property.name);
return {
...property,
typeAnnotation: this.process(
propertyStructName,
structContext,
resolveAlias,
property.typeAnnotation,
),
};
return _objectSpread({}, property, {
typeAnnotation: this.process(propertyStructName, structContext, resolveAlias, property.typeAnnotation)
});
});

@@ -174,5 +117,7 @@

context: 'REGULAR',
properties: properties,
properties: properties
});
break;
case 'CONSTANTS':

@@ -182,7 +127,9 @@ this._structs.set(structName, {

context: 'CONSTANTS',
properties: properties,
properties: properties
});
break;
default:
(structContext );
structContext;
throw new Error(`Detected an invalid struct context: ${structContext}`);

@@ -192,13 +139,14 @@ }

getAllStructs() {
getAllStructs() {
return [...this._structs.values()];
}
getStruct(name ) {
getStruct(name) {
return this._structs.get(name);
}
}
module.exports = {
StructCollector,
};
StructCollector
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,18 +10,13 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function getSafePropertyName(property ) {
function getSafePropertyName(property) {
if (property.name === 'id') {
return `${property.name}_`;
}
return property.name;
}
function getNamespacedStructName(
hasteModuleName ,
structName ,
) {
function getNamespacedStructName(hasteModuleName, structName) {
return `JS::${hasteModuleName}::${structName}`;

@@ -32,3 +27,3 @@ }

getSafePropertyName,
getNamespacedStructName,
};
getNamespacedStructName
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,20 +10,8 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const invariant = require('invariant');
function createAliasResolver(aliasMap ) {
return (aliasName ) => {
function createAliasResolver(aliasMap) {
return aliasName => {
const alias = aliasMap[aliasName];

@@ -35,16 +23,13 @@ invariant(alias != null, `Unable to resolve type alias '${aliasName}'.`);

function getModules(
schema ,
) {
return Object.keys(schema.modules).reduce (
(modules, hasteModuleName ) => {
const module = schema.modules[hasteModuleName];
if (module == null || module.type === 'Component') {
return modules;
}
modules[hasteModuleName] = module;
function getModules(schema) {
return Object.keys(schema.modules).reduce((modules, hasteModuleName) => {
const module = schema.modules[hasteModuleName];
if (module == null || module.type === 'Component') {
return modules;
},
{},
);
}
modules[hasteModuleName] = module;
return modules;
}, {});
}

@@ -54,3 +39,3 @@

createAliasResolver,
getModules,
};
getModules
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,5 +10,3 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
/*

@@ -21,168 +19,196 @@ TODO:

const fs = require('fs');
const generateComponentDescriptorH = require('./components/GenerateComponentDescriptorH.js');
const generateComponentHObjCpp = require('./components/GenerateComponentHObjCpp.js');
const generateEventEmitterCpp = require('./components/GenerateEventEmitterCpp.js');
const generateEventEmitterH = require('./components/GenerateEventEmitterH.js');
const generatePropsCpp = require('./components/GeneratePropsCpp.js');
const generatePropsH = require('./components/GeneratePropsH.js');
const generateStateCpp = require('./components/GenerateStateCpp.js');
const generateStateH = require('./components/GenerateStateH.js');
const generateModuleH = require('./modules/GenerateModuleH.js');
const generateModuleCpp = require('./modules/GenerateModuleCpp.js');
const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp');
const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js');
const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js');
const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js');
const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js');
const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js');
const generateTests = require('./components/GenerateTests.js');
const generateShadowNodeCpp = require('./components/GenerateShadowNodeCpp.js');
const generateShadowNodeH = require('./components/GenerateShadowNodeH.js');
const generateViewConfigJs = require('./components/GenerateViewConfigJs.js');
const path = require('path');
const schemaValidator = require('../SchemaValidator.js');
const generateThirdPartyFabricComponentsProviderObjCpp = require('./components/GenerateThirdPartyFabricComponentsProviderObjCpp.js');
const generateThirdPartyFabricComponentsProviderH = require('./components/GenerateThirdPartyFabricComponentsProviderH.js');
const generateViewConfigJs = require('./components/GenerateViewConfigJs.js');
const path = require('path');
const GENERATORS = {
const schemaValidator = require('../SchemaValidator.js');
const LIBRARY_GENERATORS = {
descriptors: [generateComponentDescriptorH.generate],
events: [generateEventEmitterCpp.generate, generateEventEmitterH.generate],
props: [
generateComponentHObjCpp.generate,
generatePropsCpp.generate,
generatePropsH.generate,
generatePropsJavaInterface.generate,
generatePropsJavaDelegate.generate,
],
states: [generateStateCpp.generate, generateStateH.generate],
props: [generateComponentHObjCpp.generate, generatePropsCpp.generate, generatePropsH.generate, generatePropsJavaInterface.generate, generatePropsJavaDelegate.generate],
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
componentsAndroid: [
// JNI/C++ files
generateComponentDescriptorH.generate,
generateEventEmitterCpp.generate,
generateEventEmitterH.generate,
generatePropsCpp.generate,
generatePropsH.generate,
generateShadowNodeCpp.generate,
generateShadowNodeH.generate,
// Java files
generatePropsJavaInterface.generate,
generatePropsJavaDelegate.generate,
],
componentsIOS: [
generateComponentDescriptorH.generate,
generateEventEmitterCpp.generate,
generateEventEmitterH.generate,
generateComponentHObjCpp.generate,
generatePropsCpp.generate,
generatePropsH.generate,
generateShadowNodeCpp.generate,
generateShadowNodeH.generate,
],
modulesAndroid: [
GenerateModuleJniCpp.generate,
GenerateModuleJniH.generate,
generateModuleJavaSpec.generate,
],
componentsAndroid: [// JNI/C++ files
generateComponentDescriptorH.generate, generateEventEmitterCpp.generate, generateEventEmitterH.generate, generatePropsCpp.generate, generatePropsH.generate, generateStateCpp.generate, generateStateH.generate, generateShadowNodeCpp.generate, generateShadowNodeH.generate, // Java files
generatePropsJavaInterface.generate, generatePropsJavaDelegate.generate],
componentsIOS: [generateComponentDescriptorH.generate, generateEventEmitterCpp.generate, generateEventEmitterH.generate, generateComponentHObjCpp.generate, generatePropsCpp.generate, generatePropsH.generate, generateStateCpp.generate, generateStateH.generate, generateShadowNodeCpp.generate, generateShadowNodeH.generate],
modulesAndroid: [GenerateModuleJniCpp.generate, GenerateModuleJniH.generate, generateModuleJavaSpec.generate],
modulesCxx: [generateModuleCpp.generate, generateModuleH.generate],
modulesIOS: [generateModuleObjCpp.generate],
tests: [generateTests.generate],
'shadow-nodes': [
generateShadowNodeCpp.generate,
generateShadowNodeH.generate,
],
'shadow-nodes': [generateShadowNodeCpp.generate, generateShadowNodeH.generate]
};
const SCHEMAS_GENERATORS = {
providerIOS: [generateThirdPartyFabricComponentsProviderObjCpp.generate, generateThirdPartyFabricComponentsProviderH.generate]
};
function writeMapToFiles(map , outputDir ) {
function writeMapToFiles(map) {
let success = true;
map.forEach((contents , fileName ) => {
map.forEach(file => {
try {
const location = path.join(outputDir, fileName);
const location = path.join(file.outputDir, file.name);
const dirName = path.dirname(location);
if (!fs.existsSync(dirName)) {
fs.mkdirSync(dirName, {recursive: true});
fs.mkdirSync(dirName, {
recursive: true
});
}
fs.writeFileSync(location, contents);
fs.writeFileSync(location, file.content);
} catch (error) {
success = false;
console.error(`Failed to write ${fileName} to ${outputDir}`, error);
console.error(`Failed to write ${file.name} to ${file.outputDir}`, error);
}
});
return success;
}
function checkFilesForChanges(
map ,
outputDir ,
) {
function checkFilesForChanges(generated) {
let hasChanged = false;
map.forEach((contents , fileName ) => {
const location = path.join(outputDir, fileName);
generated.forEach(file => {
const location = path.join(file.outputDir, file.name);
const currentContents = fs.readFileSync(location, 'utf8');
if (currentContents !== contents) {
console.error(`- ${fileName} has changed`);
if (currentContents !== file.content) {
console.error(`- ${file.name} has changed`);
hasChanged = true;
}
});
return !hasChanged;
}
function checkOrWriteFiles(generatedFiles, test) {
if (test === true) {
return checkFilesForChanges(generatedFiles);
}
return writeMapToFiles(generatedFiles);
}
module.exports = {
generate(
{libraryName, schema, outputDirectory, packageName, assumeNonnull} ,
{generators, test} ,
) {
generate({
libraryName,
schema,
outputDirectory,
packageName,
assumeNonnull
}, {
generators,
test
}) {
schemaValidator.validate(schema);
function composePath(intermediate) {
return path.join(outputDirectory, intermediate, libraryName);
}
const componentIOSOutput = composePath('react/renderer/components/');
const modulesIOSOutput = composePath('./');
const outputFoldersForGenerators = {
componentsIOS: componentIOSOutput,
modulesIOS: modulesIOSOutput,
descriptors: outputDirectory,
events: outputDirectory,
props: outputDirectory,
states: outputDirectory,
componentsAndroid: outputDirectory,
modulesAndroid: outputDirectory,
modulesCxx: outputDirectory,
tests: outputDirectory,
'shadow-nodes': outputDirectory
};
const generatedFiles = [];
for (const name of generators) {
for (const generator of GENERATORS[name]) {
generatedFiles.push(
...generator(libraryName, schema, packageName, assumeNonnull),
);
for (const generator of LIBRARY_GENERATORS[name]) {
generator(libraryName, schema, packageName, assumeNonnull).forEach((contents, fileName) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputFoldersForGenerators[name]
});
});
}
}
const filesToUpdate = new Map([...generatedFiles]);
return checkOrWriteFiles(generatedFiles, test);
},
if (test === true) {
return checkFilesForChanges(filesToUpdate, outputDirectory);
generateFromSchemas({
schemas,
outputDirectory
}, {
generators,
test
}) {
Object.keys(schemas).forEach(libraryName => schemaValidator.validate(schemas[libraryName]));
const generatedFiles = [];
for (const name of generators) {
for (const generator of SCHEMAS_GENERATORS[name]) {
generator(schemas).forEach((contents, fileName) => {
generatedFiles.push({
name: fileName,
content: contents,
outputDir: outputDirectory
});
});
}
}
return writeMapToFiles(filesToUpdate, outputDirectory);
return checkOrWriteFiles(generatedFiles, test);
},
generateViewConfig({libraryName, schema} ) {
generateViewConfig({
libraryName,
schema
}) {
schemaValidator.validate(schema);
const result = generateViewConfigJs.generate(libraryName, schema).values().next();
const result = generateViewConfigJs
.generate(libraryName, schema)
.values()
.next();
if (typeof result.value !== 'string') {

@@ -193,3 +219,4 @@ throw new Error(`Failed to generate view config for ${libraryName}`);

return result.value;
},
};
}
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,11 +10,22 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function capitalize(string ) {
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function indent(nice, spaces) {
return nice.split('\n').map((line, index) => {
if (line.length === 0 || index === 0) {
return line;
}
const emptySpaces = new Array(spaces + 1).join(' ');
return emptySpaces + line;
}).join('\n');
}
module.exports = {
capitalize,
};
indent
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,33 +10,15 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const _require = require('../utils.js'),
getValueFromTypes = _require.getValueFromTypes;
const {getValueFromTypes} = require('../utils.js');
function buildCommandSchema(property, types ) {
function buildCommandSchema(property, types) {
const name = property.key.name;
const optional = property.optional;
const value = getValueFromTypes(property.value, types);
const firstParam = value.params[0].typeAnnotation;
if (
!(
firstParam.id != null &&
firstParam.id.type === 'QualifiedTypeIdentifier' &&
firstParam.id.qualification.name === 'React' &&
firstParam.id.id.name === 'ElementRef'
)
) {
throw new Error(
`The first argument of method ${name} must be of type React.ElementRef<>`,
);
if (!(firstParam.id != null && firstParam.id.type === 'QualifiedTypeIdentifier' && firstParam.id.qualification.name === 'React' && firstParam.id.id.name === 'ElementRef')) {
throw new Error(`The first argument of method ${name} must be of type React.ElementRef<>`);
}

@@ -47,6 +29,3 @@

const paramValue = getValueFromTypes(param.typeAnnotation, types);
const type =
paramValue.type === 'GenericTypeAnnotation'
? paramValue.id.name
: paramValue.type;
const type = paramValue.type === 'GenericTypeAnnotation' ? paramValue.id.name : paramValue.type;
let returnType;

@@ -58,35 +37,39 @@

type: 'ReservedTypeAnnotation',
name: 'RootTag',
name: 'RootTag'
};
break;
case 'BooleanTypeAnnotation':
returnType = {
type: 'BooleanTypeAnnotation',
type: 'BooleanTypeAnnotation'
};
break;
case 'Int32':
returnType = {
type: 'Int32TypeAnnotation',
type: 'Int32TypeAnnotation'
};
break;
case 'Double':
returnType = {
type: 'DoubleTypeAnnotation',
type: 'DoubleTypeAnnotation'
};
break;
case 'Float':
returnType = {
type: 'FloatTypeAnnotation',
type: 'FloatTypeAnnotation'
};
break;
case 'StringTypeAnnotation':
returnType = {
type: 'StringTypeAnnotation',
type: 'StringTypeAnnotation'
};
break;
default:
(type );
throw new Error(
`Unsupported param type for method "${name}", param "${paramName}". Found ${type}`,
);
type;
throw new Error(`Unsupported param type for method "${name}", param "${paramName}". Found ${type}`);
}

@@ -96,6 +79,6 @@

name: paramName,
typeAnnotation: returnType,
optional: false,
typeAnnotation: returnType
};
});
return {

@@ -108,20 +91,14 @@ name,

returnTypeAnnotation: {
type: 'VoidTypeAnnotation',
},
},
type: 'VoidTypeAnnotation'
}
}
};
}
function getCommands(
commandTypeAST ,
types ,
) {
return commandTypeAST
.filter(property => property.type === 'ObjectTypeProperty')
.map(property => buildCommandSchema(property, types))
.filter(Boolean);
function getCommands(commandTypeAST, types) {
return commandTypeAST.filter(property => property.type === 'ObjectTypeProperty').map(property => buildCommandSchema(property, types)).filter(Boolean);
}
module.exports = {
getCommands,
};
getCommands
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,20 +10,9 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function getPropertyType(
name,
optional,
typeAnnotation,
) {
const type =
typeAnnotation.type === 'GenericTypeAnnotation'
? typeAnnotation.id.name
: typeAnnotation.type;
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
name, optional, typeAnnotation) {
const type = typeAnnotation.type === 'GenericTypeAnnotation' ? typeAnnotation.id.name : typeAnnotation.type;

@@ -36,5 +25,6 @@ switch (type) {

typeAnnotation: {
type: 'BooleanTypeAnnotation',
},
type: 'BooleanTypeAnnotation'
}
};
case 'StringTypeAnnotation':

@@ -45,5 +35,6 @@ return {

typeAnnotation: {
type: 'StringTypeAnnotation',
},
type: 'StringTypeAnnotation'
}
};
case 'Int32':

@@ -54,5 +45,6 @@ return {

typeAnnotation: {
type: 'Int32TypeAnnotation',
},
type: 'Int32TypeAnnotation'
}
};
case 'Double':

@@ -63,5 +55,6 @@ return {

typeAnnotation: {
type: 'DoubleTypeAnnotation',
},
type: 'DoubleTypeAnnotation'
}
};
case 'Float':

@@ -72,11 +65,9 @@ return {

typeAnnotation: {
type: 'FloatTypeAnnotation',
},
type: 'FloatTypeAnnotation'
}
};
case '$ReadOnly':
return getPropertyType(
name,
optional,
typeAnnotation.typeParameters.params[0],
);
return getPropertyType(name, optional, typeAnnotation.typeParameters.params[0]);
case 'ObjectTypeAnnotation':

@@ -88,5 +79,6 @@ return {

type: 'ObjectTypeAnnotation',
properties: typeAnnotation.properties.map(buildPropertiesForEvent),
},
properties: typeAnnotation.properties.map(buildPropertiesForEvent)
}
};
case 'UnionTypeAnnotation':

@@ -98,7 +90,8 @@ return {

type: 'StringEnumTypeAnnotation',
options: typeAnnotation.types.map(option => option.value),
},
options: typeAnnotation.types.map(option => option.value)
}
};
default:
(type );
type;
throw new Error(`Unable to determine event type for "${name}": ${type}`);

@@ -108,12 +101,9 @@ }

function findEventArgumentsAndType(
typeAnnotation,
types,
bubblingType,
paperName,
) {
function findEventArgumentsAndType(typeAnnotation, types, bubblingType, paperName) {
if (!typeAnnotation.id) {
throw new Error("typeAnnotation of event doesn't have a name");
}
const name = typeAnnotation.id.name;
if (name === '$ReadOnly') {

@@ -123,33 +113,19 @@ return {

paperTopLevelNameDeprecated: paperName,
bubblingType,
bubblingType
};
} else if (name === 'BubblingEventHandler' || name === 'DirectEventHandler') {
const eventType = name === 'BubblingEventHandler' ? 'bubble' : 'direct';
const paperTopLevelNameDeprecated =
typeAnnotation.typeParameters.params.length > 1
? typeAnnotation.typeParameters.params[1].value
: null;
if (
typeAnnotation.typeParameters.params[0].type ===
'NullLiteralTypeAnnotation'
) {
const paperTopLevelNameDeprecated = typeAnnotation.typeParameters.params.length > 1 ? typeAnnotation.typeParameters.params[1].value : null;
if (typeAnnotation.typeParameters.params[0].type === 'NullLiteralTypeAnnotation') {
return {
argumentProps: [],
bubblingType: eventType,
paperTopLevelNameDeprecated,
paperTopLevelNameDeprecated
};
}
return findEventArgumentsAndType(
typeAnnotation.typeParameters.params[0],
types,
eventType,
paperTopLevelNameDeprecated,
);
return findEventArgumentsAndType(typeAnnotation.typeParameters.params[0], types, eventType, paperTopLevelNameDeprecated);
} else if (types[name]) {
return findEventArgumentsAndType(
types[name].right,
types,
bubblingType,
paperName,
);
return findEventArgumentsAndType(types[name].right, types, bubblingType, paperName);
} else {

@@ -159,52 +135,40 @@ return {

bubblingType: null,
paperTopLevelNameDeprecated: null,
paperTopLevelNameDeprecated: null
};
}
}
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function buildPropertiesForEvent(property) {
function buildPropertiesForEvent(property) {
const name = property.key.name;
const optional =
property.value.type === 'NullableTypeAnnotation' || property.optional;
let typeAnnotation =
property.value.type === 'NullableTypeAnnotation'
? property.value.typeAnnotation
: property.value;
const optional = property.value.type === 'NullableTypeAnnotation' || property.optional;
let typeAnnotation = property.value.type === 'NullableTypeAnnotation' ? property.value.typeAnnotation : property.value;
return getPropertyType(name, optional, typeAnnotation);
}
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function getEventArgument(argumentProps, name) {
return {
type: 'ObjectTypeAnnotation',
properties: argumentProps.map(buildPropertiesForEvent),
properties: argumentProps.map(buildPropertiesForEvent)
};
}
function buildEventSchema(
types ,
property ,
) {
function buildEventSchema(types, property) {
const name = property.key.name;
const optional =
property.optional || property.value.type === 'NullableTypeAnnotation';
const optional = property.optional || property.value.type === 'NullableTypeAnnotation';
let typeAnnotation = property.value.type === 'NullableTypeAnnotation' ? property.value.typeAnnotation : property.value;
let typeAnnotation =
property.value.type === 'NullableTypeAnnotation'
? property.value.typeAnnotation
: property.value;
if (
typeAnnotation.type !== 'GenericTypeAnnotation' ||
(typeAnnotation.id.name !== 'BubblingEventHandler' &&
typeAnnotation.id.name !== 'DirectEventHandler')
) {
if (typeAnnotation.type !== 'GenericTypeAnnotation' || typeAnnotation.id.name !== 'BubblingEventHandler' && typeAnnotation.id.name !== 'DirectEventHandler') {
return null;
}
const {
argumentProps,
bubblingType,
paperTopLevelNameDeprecated,
} = findEventArgumentsAndType(typeAnnotation, types);
const _findEventArgumentsAn = findEventArgumentsAndType(typeAnnotation, types),
argumentProps = _findEventArgumentsAn.argumentProps,
bubblingType = _findEventArgumentsAn.bubblingType,
paperTopLevelNameDeprecated = _findEventArgumentsAn.paperTopLevelNameDeprecated;

@@ -220,4 +184,4 @@ if (bubblingType && argumentProps) {

type: 'EventTypeAnnotation',
argument: getEventArgument(argumentProps, name),
},
argument: getEventArgument(argumentProps, name)
}
};

@@ -232,4 +196,4 @@ }

type: 'EventTypeAnnotation',
argument: getEventArgument(argumentProps, name),
},
argument: getEventArgument(argumentProps, name)
}
};

@@ -245,25 +209,11 @@ }

}
}
} // $FlowFixMe[unclear-type] there's no flowtype for ASTs
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
function getEvents(
eventTypeAST ,
types ,
) {
return eventTypeAST
.filter(property => property.type === 'ObjectTypeProperty')
.map(property => buildEventSchema(types, property))
.filter(Boolean);
function getEvents(eventTypeAST, types) {
return eventTypeAST.filter(property => property.type === 'ObjectTypeProperty').map(property => buildEventSchema(types, property)).filter(Boolean);
}
module.exports = {
getEvents,
};
getEvents
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,12 +10,9 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function extendsForProp(prop , types ) {
function extendsForProp(prop, types) {
if (!prop.argument) {
console.log('null', prop);
}
const name = prop.argument.id.name;

@@ -32,32 +29,19 @@

type: 'ReactNativeBuiltInType',
knownTypeName: 'ReactNativeCoreViewProps',
knownTypeName: 'ReactNativeCoreViewProps'
};
default: {
throw new Error(`Unable to handle prop spread: ${name}`);
}
default:
{
throw new Error(`Unable to handle prop spread: ${name}`);
}
}
}
function removeKnownExtends(
typeDefinition ,
types ,
) {
return typeDefinition.filter(
prop =>
prop.type !== 'ObjectTypeSpreadProperty' ||
extendsForProp(prop, types) === null,
);
}
function removeKnownExtends(typeDefinition, types) {
return typeDefinition.filter(prop => prop.type !== 'ObjectTypeSpreadProperty' || extendsForProp(prop, types) === null);
} // $FlowFixMe[unclear-type] there's no flowtype for ASTs
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
function getExtendsProps(
typeDefinition ,
types ,
) {
return typeDefinition
.filter(prop => prop.type === 'ObjectTypeSpreadProperty')
.map(prop => extendsForProp(prop, types))
.filter(Boolean);
function getExtendsProps(typeDefinition, types) {
return typeDefinition.filter(prop => prop.type === 'ObjectTypeSpreadProperty').map(prop => extendsForProp(prop, types)).filter(Boolean);
}

@@ -67,3 +51,3 @@

getExtendsProps,
removeKnownExtends,
};
removeKnownExtends
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,25 +10,43 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {getCommands} = require('./commands');
const {getEvents} = require('./events');
const {getProps, getPropProperties} = require('./props');
const {getCommandOptions, getOptions} = require('./options');
const {getExtendsProps, removeKnownExtends} = require('./extends');
const {getTypes} = require('../utils');
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const _require = require('../utils'),
getTypes = _require.getTypes;
const _require2 = require('./commands'),
getCommands = _require2.getCommands;
const _require3 = require('./events'),
getEvents = _require3.getEvents;
const _require4 = require('./extends'),
getExtendsProps = _require4.getExtendsProps,
removeKnownExtends = _require4.removeKnownExtends;
const _require5 = require('./options'),
getCommandOptions = _require5.getCommandOptions,
getOptions = _require5.getOptions;
const _require6 = require('./props'),
getProps = _require6.getProps;
const _require7 = require('./componentsUtils.js'),
getProperties = _require7.getProperties;
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function findComponentConfig(ast) {
const foundConfigs = [];
const defaultExports = ast.body.filter(
node => node.type === 'ExportDefaultDeclaration',
);
const defaultExports = ast.body.filter(node => node.type === 'ExportDefaultDeclaration');
defaultExports.forEach(statement => {
let declaration = statement.declaration;
let declaration = statement.declaration; // codegenNativeComponent can be nested inside a cast
// expression so we need to go one level deeper
// codegenNativeComponent can be nested inside a cast
// expression so we need to go one level deeper
if (declaration.type === 'TypeCastExpression') {

@@ -42,13 +60,14 @@ declaration = declaration.expression;

const funcArgumentParams = declaration.arguments;
const nativeComponentType = {
propsTypeName: typeArgumentParams[0].id.name,
componentName: funcArgumentParams[0].value
};
const nativeComponentType = {};
nativeComponentType.propsTypeName = typeArgumentParams[0].id.name;
nativeComponentType.componentName = funcArgumentParams[0].value;
if (funcArgumentParams.length > 1) {
nativeComponentType.optionsExpression = funcArgumentParams[1];
}
foundConfigs.push(nativeComponentType);
}
} catch (e) {
// ignore
} catch (e) {// ignore
}

@@ -60,2 +79,3 @@ });

}
if (foundConfigs.length > 1) {

@@ -66,43 +86,34 @@ throw new Error('Only one component is supported per file');

const foundConfig = foundConfigs[0];
const namedExports = ast.body.filter(node => node.type === 'ExportNamedDeclaration');
const commandsTypeNames = namedExports.map(statement => {
let callExpression;
let calleeName;
const namedExports = ast.body.filter(
node => node.type === 'ExportNamedDeclaration',
);
try {
callExpression = statement.declaration.declarations[0].init;
calleeName = callExpression.callee.name;
} catch (e) {
return;
}
const commandsTypeNames = namedExports
.map(statement => {
let callExpression;
let calleeName;
try {
callExpression = statement.declaration.declarations[0].init;
calleeName = callExpression.callee.name;
} catch (e) {
return;
}
if (calleeName !== 'codegenNativeCommands') {
return;
} // const statement.declaration.declarations[0].init
if (calleeName !== 'codegenNativeCommands') {
return;
}
// const statement.declaration.declarations[0].init
if (callExpression.arguments.length !== 1) {
throw new Error(
'codegenNativeCommands must be passed options including the supported commands',
);
}
if (callExpression.arguments.length !== 1) {
throw new Error('codegenNativeCommands must be passed options including the supported commands');
}
const typeArgumentParam = callExpression.typeArguments.params[0];
const typeArgumentParam = callExpression.typeArguments.params[0];
if (typeArgumentParam.type !== 'GenericTypeAnnotation') {
throw new Error(
"codegenNativeCommands doesn't support inline definitions. Specify a file local type alias",
);
}
if (typeArgumentParam.type !== 'GenericTypeAnnotation') {
throw new Error("codegenNativeCommands doesn't support inline definitions. Specify a file local type alias");
}
return {
commandTypeName: typeArgumentParam.id.name,
commandOptionsExpression: callExpression.arguments[0],
};
})
.filter(Boolean);
return {
commandTypeName: typeArgumentParam.id.name,
commandOptionsExpression: callExpression.arguments[0]
};
}).filter(Boolean);

@@ -113,16 +124,12 @@ if (commandsTypeNames.length > 1) {

return {
...foundConfig,
commandTypeName:
commandsTypeNames[0] == null
? null
: commandsTypeNames[0].commandTypeName,
commandOptionsExpression:
commandsTypeNames[0] == null
? null
: commandsTypeNames[0].commandOptionsExpression,
};
return _objectSpread({}, foundConfig, {
commandTypeName: commandsTypeNames[0] == null ? null : commandsTypeNames[0].commandTypeName,
commandOptionsExpression: commandsTypeNames[0] == null ? null : commandsTypeNames[0].commandOptionsExpression
});
}
function getCommandProperties(commandTypeName, types, commandOptions) {
function getCommandProperties(
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
commandTypeName, types, commandOptions) {
if (commandTypeName == null) {

@@ -135,66 +142,44 @@ return [];

if (typeAlias.type !== 'InterfaceDeclaration') {
throw new Error(
`The type argument for codegenNativeCommands must be an interface, received ${typeAlias.type}`,
);
throw new Error(`The type argument for codegenNativeCommands must be an interface, received ${typeAlias.type}`);
}
let properties;
try {
properties = typeAlias.body.properties;
} catch (e) {
throw new Error(
`Failed to find type definition for "${commandTypeName}", please check that you have a valid codegen flow file`,
);
throw new Error(`Failed to find type definition for "${commandTypeName}", please check that you have a valid codegen flow file`);
}
const flowPropertyNames = properties
.map(property => property && property.key && property.key.name)
.filter(Boolean);
const flowPropertyNames = properties.map(property => property && property.key && property.key.name).filter(Boolean);
if (commandOptions == null || commandOptions.supportedCommands == null) {
throw new Error(
'codegenNativeCommands must be given an options object with supportedCommands array',
);
throw new Error('codegenNativeCommands must be given an options object with supportedCommands array');
}
if (
commandOptions.supportedCommands.length !== flowPropertyNames.length ||
!commandOptions.supportedCommands.every(supportedCommand =>
flowPropertyNames.includes(supportedCommand),
)
) {
throw new Error(
`codegenNativeCommands expected the same supportedCommands specified in the ${commandTypeName} interface: ${flowPropertyNames.join(
', ',
)}`,
);
if (commandOptions.supportedCommands.length !== flowPropertyNames.length || !commandOptions.supportedCommands.every(supportedCommand => flowPropertyNames.includes(supportedCommand))) {
throw new Error(`codegenNativeCommands expected the same supportedCommands specified in the ${commandTypeName} interface: ${flowPropertyNames.join(', ')}`);
}
return properties;
}
} // $FlowFixMe[signature-verification-failure] there's no flowtype for AST
// $FlowFixMe[signature-verification-failure] there's no flowtype for AST
function buildComponentSchema(ast) {
const {
componentName,
propsTypeName,
commandTypeName,
commandOptionsExpression,
optionsExpression,
} = findComponentConfig(ast);
/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
function buildComponentSchema(ast) {
const _findComponentConfig = findComponentConfig(ast),
componentName = _findComponentConfig.componentName,
propsTypeName = _findComponentConfig.propsTypeName,
commandTypeName = _findComponentConfig.commandTypeName,
commandOptionsExpression = _findComponentConfig.commandOptionsExpression,
optionsExpression = _findComponentConfig.optionsExpression;
const types = getTypes(ast);
const propProperties = getPropProperties(propsTypeName, types);
const propProperties = getProperties(propsTypeName, types);
const commandOptions = getCommandOptions(commandOptionsExpression);
const commandProperties = getCommandProperties(
commandTypeName,
types,
commandOptions,
);
const commandProperties = getCommandProperties(commandTypeName, types, commandOptions);
const extendsProps = getExtendsProps(propProperties, types);
const options = getOptions(optionsExpression);
const nonExtendsProps = removeKnownExtends(propProperties, types);

@@ -204,3 +189,2 @@ const props = getProps(nonExtendsProps, types);

const commands = getCommands(commandProperties, types);
return {

@@ -213,3 +197,3 @@ filename: componentName,

props,
commands,
commands
};

@@ -219,3 +203,3 @@ }

module.exports = {
buildComponentSchema,
};
buildComponentSchema
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,17 +10,5 @@ * This source code is licensed under the MIT license found in the

*/
'use strict'; // $FlowFixMe[unclear-type] there's no flowtype for ASTs
'use strict';
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
function getCommandOptions(
commandOptionsExpression ,
) {
function getCommandOptions(commandOptionsExpression) {
if (commandOptionsExpression == null) {

@@ -31,17 +19,10 @@ return null;

let foundOptions;
try {
foundOptions = commandOptionsExpression.properties.reduce(
(options, prop) => {
options[prop.key.name] = (
(prop && prop.value && prop.value.elements) ||
[]
).map(element => element && element.value);
return options;
},
{},
);
foundOptions = commandOptionsExpression.properties.reduce((options, prop) => {
options[prop.key.name] = (prop && prop.value && prop.value.elements || []).map(element => element && element.value);
return options;
}, {});
} catch (e) {
throw new Error(
'Failed to parse command options, please check that they are defined correctly',
);
throw new Error('Failed to parse command options, please check that they are defined correctly');
}

@@ -52,31 +33,25 @@

function getOptions(optionsExpression ) {
function getOptions(optionsExpression) {
if (!optionsExpression) {
return null;
}
let foundOptions;
try {
foundOptions = optionsExpression.properties.reduce((options, prop) => {
if (prop.value.type === 'ArrayExpression') {
options[prop.key.name] = prop.value.elements.map(
element => element.value,
);
options[prop.key.name] = prop.value.elements.map(element => element.value);
} else {
options[prop.key.name] = prop.value.value;
}
return options;
}, {});
} catch (e) {
throw new Error(
'Failed to parse codegen options, please check that they are defined correctly',
);
throw new Error('Failed to parse codegen options, please check that they are defined correctly');
}
if (
foundOptions.paperComponentName &&
foundOptions.paperComponentNameDeprecated
) {
throw new Error(
'Failed to parse codegen options, cannot use both paperComponentName and paperComponentNameDeprecated',
);
if (foundOptions.paperComponentName && foundOptions.paperComponentNameDeprecated) {
throw new Error('Failed to parse codegen options, cannot use both paperComponentName and paperComponentNameDeprecated');
}

@@ -89,3 +64,3 @@

getCommandOptions,
getOptions,
};
getOptions
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,467 +10,35 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {getValueFromTypes} = require('../utils.js');
const _require = require('./componentsUtils.js'),
flattenProperties = _require.flattenProperties,
getSchemaInfo = _require.getSchemaInfo,
getTypeAnnotation = _require.getTypeAnnotation; // $FlowFixMe[unclear-type] there's no flowtype for ASTs
function getPropProperties(
propsTypeName ,
types ,
) {
const typeAlias = types[propsTypeName];
try {
return typeAlias.right.typeParameters.params[0].properties;
} catch (e) {
throw new Error(
`Failed to find type definition for "${propsTypeName}", please check that you have a valid codegen flow file`,
);
}
}
function buildPropSchema(property, types) {
const info = getSchemaInfo(property, types);
function getTypeAnnotationForArray(name, typeAnnotation, defaultValue, types) {
const extractedTypeAnnotation = getValueFromTypes(typeAnnotation, types);
if (extractedTypeAnnotation.type === 'NullableTypeAnnotation') {
throw new Error(
'Nested optionals such as "$ReadOnlyArray<?boolean>" are not supported, please declare optionals at the top level of value definitions as in "?$ReadOnlyArray<boolean>"',
);
}
if (
extractedTypeAnnotation.type === 'GenericTypeAnnotation' &&
extractedTypeAnnotation.id.name === 'WithDefault'
) {
throw new Error(
'Nested defaults such as "$ReadOnlyArray<WithDefault<boolean, false>>" are not supported, please declare defaults at the top level of value definitions as in "WithDefault<$ReadOnlyArray<boolean>, false>"',
);
}
if (extractedTypeAnnotation.type === 'GenericTypeAnnotation') {
// Resolve the type alias if it's not defined inline
const objectType = getValueFromTypes(extractedTypeAnnotation, types);
if (objectType.id.name === '$ReadOnly') {
return {
type: 'ObjectTypeAnnotation',
properties: flattenProperties(
objectType.typeParameters.params[0].properties,
types,
)
.map(prop => buildPropSchema(prop, types))
.filter(Boolean),
};
}
if (objectType.id.name === '$ReadOnlyArray') {
// We need to go yet another level deeper to resolve
// types that may be defined in a type alias
const nestedObjectType = getValueFromTypes(
objectType.typeParameters.params[0],
types,
);
return {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'ObjectTypeAnnotation',
properties: flattenProperties(
nestedObjectType.typeParameters.params[0].properties,
types,
)
.map(prop => buildPropSchema(prop, types))
.filter(Boolean),
},
};
}
}
const type =
extractedTypeAnnotation.type === 'GenericTypeAnnotation'
? extractedTypeAnnotation.id.name
: extractedTypeAnnotation.type;
switch (type) {
case 'ImageSource':
return {
type: 'ReservedPropTypeAnnotation',
name: 'ImageSourcePrimitive',
};
case 'ColorValue':
case 'ProcessedColorValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'ColorPrimitive',
};
case 'PointValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'PointPrimitive',
};
case 'EdgeInsetsValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'EdgeInsetsPrimitive',
};
case 'Stringish':
return {
type: 'StringTypeAnnotation',
};
case 'Int32':
return {
type: 'Int32TypeAnnotation',
};
case 'Double':
return {
type: 'DoubleTypeAnnotation',
};
case 'Float':
return {
type: 'FloatTypeAnnotation',
};
case 'BooleanTypeAnnotation':
return {
type: 'BooleanTypeAnnotation',
};
case 'StringTypeAnnotation':
return {
type: 'StringTypeAnnotation',
};
case 'UnionTypeAnnotation':
typeAnnotation.types.reduce((lastType, currType) => {
if (lastType && currType.type !== lastType.type) {
throw new Error(`Mixed types are not supported (see "${name}")`);
}
return currType;
});
if (defaultValue === null) {
throw new Error(`A default enum value is required for "${name}"`);
}
const unionType = typeAnnotation.types[0].type;
if (unionType === 'StringLiteralTypeAnnotation') {
return {
type: 'StringEnumTypeAnnotation',
default: (defaultValue ),
options: typeAnnotation.types.map(option => option.value),
};
} else if (unionType === 'NumberLiteralTypeAnnotation') {
throw new Error(
`Arrays of int enums are not supported (see: "${name}")`,
);
} else {
throw new Error(
`Unsupported union type for "${name}", recieved "${unionType}"`,
);
}
default:
(type );
throw new Error(`Unknown prop type for "${name}": ${type}`);
}
}
function getTypeAnnotation(
name,
annotation,
defaultValue,
withNullDefault,
types,
) {
const typeAnnotation = getValueFromTypes(annotation, types);
if (
typeAnnotation.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === '$ReadOnlyArray'
) {
return {
type: 'ArrayTypeAnnotation',
elementType: getTypeAnnotationForArray(
name,
typeAnnotation.typeParameters.params[0],
defaultValue,
types,
),
};
}
if (
typeAnnotation.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === '$ReadOnly'
) {
return {
type: 'ObjectTypeAnnotation',
properties: flattenProperties(
typeAnnotation.typeParameters.params[0].properties,
types,
)
.map(prop => buildPropSchema(prop, types))
.filter(Boolean),
};
}
const type =
typeAnnotation.type === 'GenericTypeAnnotation'
? typeAnnotation.id.name
: typeAnnotation.type;
switch (type) {
case 'ImageSource':
return {
type: 'ReservedPropTypeAnnotation',
name: 'ImageSourcePrimitive',
};
case 'ColorValue':
case 'ProcessedColorValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'ColorPrimitive',
};
case 'ColorArrayValue':
return {
type: 'ArrayTypeAnnotation',
elementType: {
type: 'ReservedPropTypeAnnotation',
name: 'ColorPrimitive',
},
};
case 'PointValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'PointPrimitive',
};
case 'EdgeInsetsValue':
return {
type: 'ReservedPropTypeAnnotation',
name: 'EdgeInsetsPrimitive',
};
case 'Int32':
return {
type: 'Int32TypeAnnotation',
default: ((defaultValue ? defaultValue : 0) ),
};
case 'Double':
return {
type: 'DoubleTypeAnnotation',
default: ((defaultValue ? defaultValue : 0) ),
};
case 'Float':
return {
type: 'FloatTypeAnnotation',
default: withNullDefault
? (defaultValue )
: ((defaultValue ? defaultValue : 0) ),
};
case 'BooleanTypeAnnotation':
return {
type: 'BooleanTypeAnnotation',
default: withNullDefault
? (defaultValue )
: ((defaultValue == null ? false : defaultValue) ),
};
case 'StringTypeAnnotation':
if (typeof defaultValue !== 'undefined') {
return {
type: 'StringTypeAnnotation',
default: (defaultValue ),
};
}
throw new Error(`A default string (or null) is required for "${name}"`);
case 'Stringish':
if (typeof defaultValue !== 'undefined') {
return {
type: 'StringTypeAnnotation',
default: (defaultValue ),
};
}
throw new Error(`A default string (or null) is required for "${name}"`);
case 'UnionTypeAnnotation':
typeAnnotation.types.reduce((lastType, currType) => {
if (lastType && currType.type !== lastType.type) {
throw new Error(`Mixed types are not supported (see "${name}")`);
}
return currType;
});
if (defaultValue === null) {
throw new Error(`A default enum value is required for "${name}"`);
}
const unionType = typeAnnotation.types[0].type;
if (unionType === 'StringLiteralTypeAnnotation') {
return {
type: 'StringEnumTypeAnnotation',
default: (defaultValue ),
options: typeAnnotation.types.map(option => option.value),
};
} else if (unionType === 'NumberLiteralTypeAnnotation') {
return {
type: 'Int32EnumTypeAnnotation',
default: (defaultValue ),
options: typeAnnotation.types.map(option => option.value),
};
} else {
throw new Error(
`Unsupported union type for "${name}", received "${unionType}"`,
);
}
case 'NumberTypeAnnotation':
throw new Error(
`Cannot use "${type}" type annotation for "${name}": must use a specific numeric type like Int32, Double, or Float`,
);
default:
(type );
throw new Error(`Unknown prop type for "${name}": "${type}"`);
}
}
function buildPropSchema(
property,
types ,
) {
const name = property.key.name;
const value = getValueFromTypes(property.value, types);
let typeAnnotation =
value.type === 'NullableTypeAnnotation' ? value.typeAnnotation : value;
const optional =
value.type === 'NullableTypeAnnotation' ||
property.optional ||
(value.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault');
if (
!property.optional &&
value.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault'
) {
throw new Error(
`key ${name} must be optional if used with WithDefault<> annotation`,
);
}
if (
value.type === 'NullableTypeAnnotation' &&
typeAnnotation.type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault'
) {
throw new Error(
'WithDefault<> is optional and does not need to be marked as optional. Please remove the ? annotation in front of it.',
);
}
let type = typeAnnotation.type;
if (
type === 'GenericTypeAnnotation' &&
(typeAnnotation.id.name === 'DirectEventHandler' ||
typeAnnotation.id.name === 'BubblingEventHandler')
) {
if (info == null) {
return null;
}
if (
name === 'style' &&
type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'ViewStyleProp'
) {
return null;
}
let defaultValue = null;
let withNullDefault = false;
if (
type === 'GenericTypeAnnotation' &&
typeAnnotation.id.name === 'WithDefault'
) {
if (typeAnnotation.typeParameters.params.length === 1) {
throw new Error(
`WithDefault requires two parameters, did you forget to provide a default value for "${name}"?`,
);
}
defaultValue = typeAnnotation.typeParameters.params[1].value;
const defaultValueType = typeAnnotation.typeParameters.params[1].type;
typeAnnotation = typeAnnotation.typeParameters.params[0];
type =
typeAnnotation.type === 'GenericTypeAnnotation'
? typeAnnotation.id.name
: typeAnnotation.type;
if (defaultValueType === 'NullLiteralTypeAnnotation') {
defaultValue = null;
withNullDefault = true;
}
}
const name = info.name,
optional = info.optional,
typeAnnotation = info.typeAnnotation,
defaultValue = info.defaultValue,
withNullDefault = info.withNullDefault;
return {
name,
optional,
typeAnnotation: getTypeAnnotation(
name,
typeAnnotation,
defaultValue,
withNullDefault,
types,
),
typeAnnotation: getTypeAnnotation(name, typeAnnotation, defaultValue, withNullDefault, types, buildPropSchema)
};
}
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
function verifyPropNotAlreadyDefined(
props ,
needleProp ,
) {
const propName = needleProp.key.name;
const foundProp = props.some(prop => prop.key.name === propName);
if (foundProp) {
throw new Error(`A prop was already defined with the name ${propName}`);
}
function getProps(typeDefinition, types) {
return flattenProperties(typeDefinition, types).map(property => buildPropSchema(property, types)).filter(Boolean);
}
function flattenProperties(
typeDefinition ,
types ,
) {
return typeDefinition
.map(property => {
if (property.type === 'ObjectTypeProperty') {
return property;
} else if (property.type === 'ObjectTypeSpreadProperty') {
return flattenProperties(
getPropProperties(property.argument.id.name, types),
types,
);
}
})
.reduce((acc, item) => {
if (Array.isArray(item)) {
item.forEach(prop => {
verifyPropNotAlreadyDefined(acc, prop);
});
return acc.concat(item);
} else {
verifyPropNotAlreadyDefined(acc, item);
acc.push(item);
return acc;
}
}, [])
.filter(Boolean);
}
function getProps(
typeDefinition ,
types ,
) {
return flattenProperties(typeDefinition, types)
.map(property => buildPropSchema(property, types))
.filter(Boolean);
}
module.exports = {
getProps,
getPropProperties,
};
getProps
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -7,28 +7,13 @@ * This source code is licensed under the MIT license found in the

*
* strict
* @format
* strict-local
*/
'use strict';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function wrapComponentSchema({

@@ -41,4 +26,4 @@ filename,

options,
commands,
} ) {
commands
}) {
return {

@@ -49,12 +34,11 @@ modules: {

components: {
[componentName]: {
...(options || {}),
[componentName]: _objectSpread({}, options || {}, {
extendsProps,
events,
props,
commands,
},
},
},
},
commands
})
}
}
}
};

@@ -64,3 +48,3 @@ }

module.exports = {
wrapComponentSchema,
};
wrapComponentSchema
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,127 +10,64 @@ * This source code is licensed under the MIT license found in the

*/
'use strict'; // $FlowFixMe[untyped-import] there's no flowtype flow-parser
'use strict';
const flowParser = require('flow-parser');
// $FlowFixMe[untyped-import] there's no flowtype flow-parser
const flowParser = require('flow-parser');
const fs = require('fs');
const path = require('path');
const {buildComponentSchema} = require('./components');
const {wrapComponentSchema} = require('./components/schema');
const {buildModuleSchema} = require('./modules');
const {wrapModuleSchema} = require('./modules/schema');
const {
createParserErrorCapturer,
visit,
isModuleRegistryCall,
} = require('./utils');
const invariant = require('invariant');
function getConfigType(
// TODO(T71778680): Flow-type this node.
ast ,
) {
let isComponent = false;
let isModule = false;
const _require = require('../utils'),
buildSchemaFromConfigType = _require.buildSchemaFromConfigType,
getConfigType = _require.getConfigType,
isModuleRegistryCall = _require.isModuleRegistryCall;
visit(ast, {
const _require2 = require('./components'),
buildComponentSchema = _require2.buildComponentSchema;
const _require3 = require('./components/schema'),
wrapComponentSchema = _require3.wrapComponentSchema;
const _require4 = require('./modules'),
buildModuleSchema = _require4.buildModuleSchema;
function Visitor(infoMap) {
return {
CallExpression(node) {
if (
node.callee.type === 'Identifier' &&
node.callee.name === 'codegenNativeComponent'
) {
isComponent = true;
if (node.callee.type === 'Identifier' && node.callee.name === 'codegenNativeComponent') {
infoMap.isComponent = true;
}
if (isModuleRegistryCall(node)) {
isModule = true;
infoMap.isModule = true;
}
},
InterfaceExtends(node) {
if (node.id.name === 'TurboModule') {
isModule = true;
infoMap.isModule = true;
}
},
});
}
if (isModule && isComponent) {
throw new Error(
'Found type extending "TurboModule" and exported "codegenNativeComponent" declaration in one file. Split them into separated files.',
);
}
if (isModule) {
return 'module';
} else if (isComponent) {
return 'component';
} else {
return 'none';
}
};
}
function buildSchema(contents , filename ) {
function buildSchema(contents, filename) {
// Early return for non-Spec JavaScript files
if (
!contents.includes('codegenNativeComponent') &&
!contents.includes('TurboModule')
) {
return {modules: {}};
if (!contents.includes('codegenNativeComponent') && !contents.includes('TurboModule')) {
return {
modules: {}
};
}
const ast = flowParser.parse(contents);
const configType = getConfigType(ast);
switch (configType) {
case 'component': {
return wrapComponentSchema(buildComponentSchema(ast));
}
case 'module': {
if (filename === undefined || filename === null) {
throw new Error('Filepath expected while parasing a module');
}
const hasteModuleName = path.basename(filename).replace(/\.js$/, '');
const [parsingErrors, tryParse] = createParserErrorCapturer();
const schema = tryParse(() =>
buildModuleSchema(hasteModuleName, ast, tryParse),
);
if (parsingErrors.length > 0) {
/**
* TODO(T77968131): We have two options:
* - Throw the first error, but indicate there are more then one errors.
* - Display all errors, nicely formatted.
*
* For the time being, we're just throw the first error.
**/
throw parsingErrors[0];
}
invariant(
schema != null,
'When there are no parsing errors, the schema should not be null',
);
return wrapModuleSchema(schema, hasteModuleName);
}
default:
return {modules: {}};
}
const ast = flowParser.parse(contents, {
enums: true
});
const configType = getConfigType(ast, Visitor);
return buildSchemaFromConfigType(configType, filename, ast, wrapComponentSchema, buildComponentSchema, buildModuleSchema);
}
function parseFile(filename ) {
function parseModuleFixture(filename) {
const contents = fs.readFileSync(filename, 'utf8');
return buildSchema(contents, filename);
}
function parseModuleFixture(filename ) {
const contents = fs.readFileSync(filename, 'utf8');
return buildSchema(contents, 'path/NativeSampleTurboModule.js');
}
function parseString(contents , filename ) {
function parseString(contents, filename) {
return buildSchema(contents, filename);

@@ -140,5 +77,5 @@ }

module.exports = {
parseFile,
buildSchema,
parseModuleFixture,
parseString,
};
parseString
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,526 +10,276 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
const {
resolveTypeAnnotation,
getTypes,
visit,
isModuleRegistryCall,
} = require('../utils.js');
const {unwrapNullable, wrapNullable} = require('./utils');
const {
IncorrectlyParameterizedFlowGenericParserError,
MisnamedModuleFlowInterfaceParserError,
ModuleFlowInterfaceNotFoundParserError,
MoreThanOneModuleFlowInterfaceParserError,
UnnamedFunctionParamParserError,
UnsupportedArrayElementTypeAnnotationParserError,
UnsupportedFlowGenericParserError,
UnsupportedFlowTypeAnnotationParserError,
UnsupportedFunctionParamTypeAnnotationParserError,
UnsupportedFunctionReturnTypeAnnotationParserError,
UnsupportedModulePropertyParserError,
UnsupportedObjectPropertyTypeAnnotationParserError,
UnsupportedObjectPropertyValueTypeAnnotationParserError,
UnusedModuleFlowInterfaceParserError,
MoreThanOneModuleRegistryCallsParserError,
UntypedModuleRegistryCallParserError,
IncorrectModuleRegistryCallTypeParameterParserError,
IncorrectModuleRegistryCallArityParserError,
IncorrectModuleRegistryCallArgumentTypeParserError,
} = require('./errors.js');
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
const invariant = require('invariant');
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
function nullGuard (fn ) {
return fn();
}
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
function translateTypeAnnotation(
hasteModuleName ,
/**
* TODO(T71778680): Flow-type this node.
*/
flowTypeAnnotation ,
types ,
aliasMap ,
tryParse ,
) {
const {
nullable,
typeAnnotation,
typeAliasResolutionStatus,
} = resolveTypeAnnotation(flowTypeAnnotation, types);
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
switch (typeAnnotation.type) {
case 'GenericTypeAnnotation': {
switch (typeAnnotation.id.name) {
case 'RootTag': {
return wrapNullable(nullable, {
type: 'ReservedTypeAnnotation',
name: 'RootTag',
});
}
case 'Promise': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
return wrapNullable(nullable, {
type: 'PromiseTypeAnnotation',
});
}
case 'Array':
case '$ReadOnlyArray': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
const _require = require('../../parsers-utils'),
nullGuard = _require.nullGuard;
try {
/**
* TODO(T72031674): Migrate all our NativeModule specs to not use
* invalid Array ElementTypes. Then, make the elementType a required
* parameter.
*/
const [elementType, isElementTypeNullable] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
types,
aliasMap,
/**
* TODO(T72031674): Ensure that all ParsingErrors that are thrown
* while parsing the array element don't get captured and collected.
* Why? If we detect any parsing error while parsing the element,
* we should default it to null down the line, here. This is
* the correct behaviour until we migrate all our NativeModule specs
* to be parseable.
*/
nullGuard,
),
);
const _require2 = require('../../utils'),
visit = _require2.visit,
verifyPlatforms = _require2.verifyPlatforms,
isModuleRegistryCall = _require2.isModuleRegistryCall;
if (elementType.type === 'VoidTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'void',
);
}
const _require3 = require('../utils.js'),
resolveTypeAnnotation = _require3.resolveTypeAnnotation,
getTypes = _require3.getTypes;
if (elementType.type === 'PromiseTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'Promise',
);
}
const _require4 = require('../../parsers-commons'),
unwrapNullable = _require4.unwrapNullable,
wrapNullable = _require4.wrapNullable,
assertGenericTypeAnnotationHasExactlyOneTypeParameter = _require4.assertGenericTypeAnnotationHasExactlyOneTypeParameter,
parseObjectProperty = _require4.parseObjectProperty,
emitUnionTypeAnnotation = _require4.emitUnionTypeAnnotation,
translateDefault = _require4.translateDefault,
translateFunctionTypeAnnotation = _require4.translateFunctionTypeAnnotation;
if (elementType.type === 'FunctionTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
typeAnnotation.type,
'FunctionTypeAnnotation',
);
}
const _require5 = require('../../parsers-primitives'),
emitBoolean = _require5.emitBoolean,
emitDouble = _require5.emitDouble,
emitFloat = _require5.emitFloat,
emitFunction = _require5.emitFunction,
emitNumber = _require5.emitNumber,
emitInt32 = _require5.emitInt32,
emitObject = _require5.emitObject,
emitPromise = _require5.emitPromise,
emitRootTag = _require5.emitRootTag,
emitVoid = _require5.emitVoid,
emitString = _require5.emitString,
emitStringish = _require5.emitStringish,
emitMixedTypeAnnotation = _require5.emitMixedTypeAnnotation,
typeAliasResolution = _require5.typeAliasResolution;
const finalTypeAnnotation
= {
type: 'ArrayTypeAnnotation',
elementType: wrapNullable(isElementTypeNullable, elementType),
};
const _require6 = require('../../errors.js'),
UnsupportedArrayElementTypeAnnotationParserError = _require6.UnsupportedArrayElementTypeAnnotationParserError,
UnsupportedTypeAnnotationParserError = _require6.UnsupportedTypeAnnotationParserError,
IncorrectModuleRegistryCallArgumentTypeParserError = _require6.IncorrectModuleRegistryCallArgumentTypeParserError;
return wrapNullable(nullable, finalTypeAnnotation);
} catch (ex) {
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation',
});
}
}
case '$ReadOnly': {
assertGenericTypeAnnotationHasExactlyOneTypeParameter(
hasteModuleName,
typeAnnotation,
);
const _require7 = require('../../error-utils'),
throwIfModuleInterfaceNotFound = _require7.throwIfModuleInterfaceNotFound,
throwIfModuleInterfaceIsMisnamed = _require7.throwIfModuleInterfaceIsMisnamed,
throwIfUnusedModuleInterfaceParserError = _require7.throwIfUnusedModuleInterfaceParserError,
throwIfWrongNumberOfCallExpressionArgs = _require7.throwIfWrongNumberOfCallExpressionArgs,
throwIfMoreThanOneModuleRegistryCalls = _require7.throwIfMoreThanOneModuleRegistryCalls,
throwIfIncorrectModuleRegistryCallTypeParameterParserError = _require7.throwIfIncorrectModuleRegistryCallTypeParameterParserError,
throwIfUntypedModule = _require7.throwIfUntypedModule,
throwIfModuleTypeIsUnsupported = _require7.throwIfModuleTypeIsUnsupported,
throwIfMoreThanOneModuleInterfaceParserError = _require7.throwIfMoreThanOneModuleInterfaceParserError;
return translateTypeAnnotation(
hasteModuleName,
typeAnnotation.typeParameters.params[0],
types,
aliasMap,
tryParse,
);
}
case 'Stringish': {
return wrapNullable(nullable, {
type: 'StringTypeAnnotation',
});
}
case 'Int32': {
return wrapNullable(nullable, {
type: 'Int32TypeAnnotation',
});
}
case 'Double': {
return wrapNullable(nullable, {
type: 'DoubleTypeAnnotation',
});
}
case 'Float': {
return wrapNullable(nullable, {
type: 'FloatTypeAnnotation',
});
}
case 'UnsafeObject':
case 'Object': {
return wrapNullable(nullable, {
type: 'GenericObjectTypeAnnotation',
});
}
default: {
throw new UnsupportedFlowGenericParserError(
hasteModuleName,
typeAnnotation,
);
}
}
const _require8 = require('../parser.js'),
FlowParser = _require8.FlowParser;
const language = 'Flow';
const parser = new FlowParser();
function translateArrayTypeAnnotation(hasteModuleName, types, aliasMap, cxxOnly, flowArrayType, flowElementType, nullable) {
try {
/**
* TODO(T72031674): Migrate all our NativeModule specs to not use
* invalid Array ElementTypes. Then, make the elementType a required
* parameter.
*/
const _unwrapNullable = unwrapNullable(translateTypeAnnotation(hasteModuleName, flowElementType, types, aliasMap,
/**
* TODO(T72031674): Ensure that all ParsingErrors that are thrown
* while parsing the array element don't get captured and collected.
* Why? If we detect any parsing error while parsing the element,
* we should default it to null down the line, here. This is
* the correct behaviour until we migrate all our NativeModule specs
* to be parseable.
*/
nullGuard, cxxOnly)),
_unwrapNullable2 = _slicedToArray(_unwrapNullable, 2),
elementType = _unwrapNullable2[0],
isElementTypeNullable = _unwrapNullable2[1];
if (elementType.type === 'VoidTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(hasteModuleName, flowElementType, flowArrayType, 'void', language);
}
case 'ObjectTypeAnnotation': {
const objectTypeAnnotation = {
type: 'ObjectTypeAnnotation',
// $FlowFixMe[missing-type-arg]
properties: (typeAnnotation.properties )
.map (
property => {
return tryParse(() => {
if (property.type !== 'ObjectTypeProperty') {
throw new UnsupportedObjectPropertyTypeAnnotationParserError(
hasteModuleName,
property,
property.type,
);
}
const {optional, key} = property;
if (elementType.type === 'PromiseTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(hasteModuleName, flowElementType, flowArrayType, 'Promise', language);
}
const [
propertyTypeAnnotation,
isPropertyNullable,
] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
property.value,
types,
aliasMap,
tryParse,
),
);
if (elementType.type === 'FunctionTypeAnnotation') {
throw new UnsupportedArrayElementTypeAnnotationParserError(hasteModuleName, flowElementType, flowArrayType, 'FunctionTypeAnnotation', language);
}
if (propertyTypeAnnotation.type === 'FunctionTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
propertyTypeAnnotation.type,
);
}
const finalTypeAnnotation = {
type: 'ArrayTypeAnnotation',
elementType: wrapNullable(isElementTypeNullable, elementType)
};
return wrapNullable(nullable, finalTypeAnnotation);
} catch (ex) {
return wrapNullable(nullable, {
type: 'ArrayTypeAnnotation'
});
}
}
if (propertyTypeAnnotation.type === 'VoidTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
'void',
);
}
function translateTypeAnnotation(hasteModuleName,
/**
* TODO(T71778680): Flow-type this node.
*/
flowTypeAnnotation, types, aliasMap, tryParse, cxxOnly) {
const _resolveTypeAnnotatio = resolveTypeAnnotation(flowTypeAnnotation, types),
nullable = _resolveTypeAnnotatio.nullable,
typeAnnotation = _resolveTypeAnnotatio.typeAnnotation,
typeAliasResolutionStatus = _resolveTypeAnnotatio.typeAliasResolutionStatus;
if (propertyTypeAnnotation.type === 'PromiseTypeAnnotation') {
throw new UnsupportedObjectPropertyValueTypeAnnotationParserError(
hasteModuleName,
property.value,
property.key,
'Promise',
);
}
switch (typeAnnotation.type) {
case 'GenericTypeAnnotation':
{
switch (typeAnnotation.id.name) {
case 'RootTag':
{
return emitRootTag(nullable);
}
return {
name: key.name,
optional,
typeAnnotation: wrapNullable(
isPropertyNullable,
propertyTypeAnnotation,
),
};
});
},
)
.filter(Boolean),
};
case 'Promise':
{
return emitPromise(hasteModuleName, typeAnnotation, parser, nullable);
}
if (!typeAliasResolutionStatus.successful) {
return wrapNullable(nullable, objectTypeAnnotation);
}
case 'Array':
case '$ReadOnlyArray':
{
assertGenericTypeAnnotationHasExactlyOneTypeParameter(hasteModuleName, typeAnnotation, parser);
return translateArrayTypeAnnotation(hasteModuleName, types, aliasMap, cxxOnly, typeAnnotation.type, typeAnnotation.typeParameters.params[0], nullable);
}
/**
* All aliases RHS are required.
*/
aliasMap[typeAliasResolutionStatus.aliasName] = objectTypeAnnotation;
case '$ReadOnly':
{
assertGenericTypeAnnotationHasExactlyOneTypeParameter(hasteModuleName, typeAnnotation, parser);
/**
* Nullability of type aliases is transitive.
*
* Consider this case:
*
* type Animal = ?{
* name: string,
* };
*
* type B = Animal
*
* export interface Spec extends TurboModule {
* +greet: (animal: B) => void;
* }
*
* In this case, we follow B to Animal, and then Animal to ?{name: string}.
*
* We:
* 1. Replace `+greet: (animal: B) => void;` with `+greet: (animal: ?Animal) => void;`,
* 2. Pretend that Animal = {name: string}.
*
* Why do we do this?
* 1. In ObjC, we need to generate a struct called Animal, not B.
* 2. This design is simpler than managing nullability within both the type alias usage, and the type alias RHS.
* 3. What does it mean for a C++ struct, which is what this type alias RHS will generate, to be nullable? ¯\_(ツ)_/¯
* Nullability is a concept that only makes sense when talking about instances (i.e: usages) of the C++ structs.
* Hence, it's better to manage nullability within the actual TypeAliasTypeAnnotation nodes, and not the
* associated ObjectTypeAnnotations.
*/
return wrapNullable(nullable, {
type: 'TypeAliasTypeAnnotation',
name: typeAliasResolutionStatus.aliasName,
});
}
case 'BooleanTypeAnnotation': {
return wrapNullable(nullable, {
type: 'BooleanTypeAnnotation',
});
}
case 'NumberTypeAnnotation': {
return wrapNullable(nullable, {
type: 'NumberTypeAnnotation',
});
}
case 'VoidTypeAnnotation': {
return wrapNullable(nullable, {
type: 'VoidTypeAnnotation',
});
}
case 'StringTypeAnnotation': {
return wrapNullable(nullable, {
type: 'StringTypeAnnotation',
});
}
case 'FunctionTypeAnnotation': {
return wrapNullable(
nullable,
translateFunctionTypeAnnotation(
hasteModuleName,
typeAnnotation,
types,
aliasMap,
tryParse,
),
);
}
default: {
throw new UnsupportedFlowTypeAnnotationParserError(
hasteModuleName,
typeAnnotation,
);
}
}
}
const _unwrapNullable3 = unwrapNullable(translateTypeAnnotation(hasteModuleName, typeAnnotation.typeParameters.params[0], types, aliasMap, tryParse, cxxOnly)),
_unwrapNullable4 = _slicedToArray(_unwrapNullable3, 2),
paramType = _unwrapNullable4[0],
isParamNullable = _unwrapNullable4[1];
function assertGenericTypeAnnotationHasExactlyOneTypeParameter(
moduleName ,
/**
* TODO(T71778680): This is a GenericTypeAnnotation. Flow type this node
*/
typeAnnotation ,
) {
if (typeAnnotation.typeParameters == null) {
throw new IncorrectlyParameterizedFlowGenericParserError(
moduleName,
typeAnnotation,
);
}
return wrapNullable(nullable || isParamNullable, paramType);
}
invariant(
typeAnnotation.typeParameters.type === 'TypeParameterInstantiation',
"assertGenericTypeAnnotationHasExactlyOneTypeParameter: Type parameters must be an AST node of type 'TypeParameterInstantiation'",
);
case 'Stringish':
{
return emitStringish(nullable);
}
if (typeAnnotation.typeParameters.params.length !== 1) {
throw new IncorrectlyParameterizedFlowGenericParserError(
moduleName,
typeAnnotation,
);
}
}
case 'Int32':
{
return emitInt32(nullable);
}
function translateFunctionTypeAnnotation(
hasteModuleName ,
// TODO(T71778680): This is a FunctionTypeAnnotation. Type this.
flowFunctionTypeAnnotation ,
types ,
aliasMap ,
tryParse ,
) {
const params = [];
case 'Double':
{
return emitDouble(nullable);
}
for (const flowParam of (flowFunctionTypeAnnotation.params )) {
const parsedParam = tryParse(() => {
if (flowParam.name == null) {
throw new UnnamedFunctionParamParserError(flowParam, hasteModuleName);
case 'Float':
{
return emitFloat(nullable);
}
case 'UnsafeObject':
case 'Object':
{
return emitObject(nullable);
}
default:
{
return translateDefault(hasteModuleName, typeAnnotation, types, nullable, parser);
}
}
}
const paramName = flowParam.name.name;
const [
paramTypeAnnotation,
isParamTypeAnnotationNullable,
] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
flowParam.typeAnnotation,
types,
aliasMap,
tryParse,
),
);
case 'ObjectTypeAnnotation':
{
const objectTypeAnnotation = {
type: 'ObjectTypeAnnotation',
// $FlowFixMe[missing-type-arg]
properties: [...typeAnnotation.properties, ...typeAnnotation.indexers].map(property => {
return tryParse(() => {
return parseObjectProperty(property, hasteModuleName, types, aliasMap, tryParse, cxxOnly, nullable, translateTypeAnnotation, parser);
});
}).filter(Boolean)
};
return typeAliasResolution(typeAliasResolutionStatus, objectTypeAnnotation, aliasMap, nullable);
}
if (paramTypeAnnotation.type === 'VoidTypeAnnotation') {
throw new UnsupportedFunctionParamTypeAnnotationParserError(
hasteModuleName,
flowParam.typeAnnotation,
paramName,
'void',
);
case 'BooleanTypeAnnotation':
{
return emitBoolean(nullable);
}
if (paramTypeAnnotation.type === 'PromiseTypeAnnotation') {
throw new UnsupportedFunctionParamTypeAnnotationParserError(
hasteModuleName,
flowParam.typeAnnotation,
paramName,
'Promise',
);
case 'NumberTypeAnnotation':
{
return emitNumber(nullable);
}
return {
name: flowParam.name.name,
optional: flowParam.optional,
typeAnnotation: wrapNullable(
isParamTypeAnnotationNullable,
paramTypeAnnotation,
),
};
});
case 'VoidTypeAnnotation':
{
return emitVoid(nullable);
}
if (parsedParam != null) {
params.push(parsedParam);
}
}
case 'StringTypeAnnotation':
{
return emitString(nullable);
}
const [returnTypeAnnotation, isReturnTypeAnnotationNullable] = unwrapNullable(
translateTypeAnnotation(
hasteModuleName,
flowFunctionTypeAnnotation.returnType,
types,
aliasMap,
tryParse,
),
);
case 'FunctionTypeAnnotation':
{
return emitFunction(nullable, hasteModuleName, typeAnnotation, types, aliasMap, tryParse, cxxOnly, translateTypeAnnotation, language);
}
if (returnTypeAnnotation.type === 'FunctionTypeAnnotation') {
throw new UnsupportedFunctionReturnTypeAnnotationParserError(
hasteModuleName,
flowFunctionTypeAnnotation.returnType,
'FunctionTypeAnnotation',
);
case 'UnionTypeAnnotation':
{
return emitUnionTypeAnnotation(nullable, hasteModuleName, typeAnnotation, parser);
}
case 'MixedTypeAnnotation':
{
if (cxxOnly) {
return emitMixedTypeAnnotation(nullable);
} // Fallthrough
}
default:
{
throw new UnsupportedTypeAnnotationParserError(hasteModuleName, typeAnnotation, language);
}
}
return {
type: 'FunctionTypeAnnotation',
returnTypeAnnotation: wrapNullable(
isReturnTypeAnnotationNullable,
returnTypeAnnotation,
),
params,
};
}
function buildPropertySchema(
hasteModuleName ,
// TODO(T71778680): This is an ObjectTypeProperty containing either:
// - a FunctionTypeAnnotation or GenericTypeAnnotation
// - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation
// Flow type this node
property ,
types ,
aliasMap ,
tryParse ,
) {
function buildPropertySchema(hasteModuleName, // TODO(T71778680): This is an ObjectTypeProperty containing either:
// - a FunctionTypeAnnotation or GenericTypeAnnotation
// - a NullableTypeAnnoation containing a FunctionTypeAnnotation or GenericTypeAnnotation
// Flow type this node
property, types, aliasMap, tryParse, cxxOnly) {
let nullable = false;
let {key, value} = property;
let key = property.key,
value = property.value;
const methodName = key.name;
const methodName = key.name;
var _resolveTypeAnnotatio2 = resolveTypeAnnotation(value, types);
({nullable, typeAnnotation: value} = resolveTypeAnnotation(value, types));
if (value.type !== 'FunctionTypeAnnotation') {
throw new UnsupportedModulePropertyParserError(
hasteModuleName,
property.value,
property.key.name,
value.type,
);
}
nullable = _resolveTypeAnnotatio2.nullable;
value = _resolveTypeAnnotatio2.typeAnnotation;
throwIfModuleTypeIsUnsupported(hasteModuleName, property.value, property.key.name, value.type, language);
return {
name: methodName,
optional: property.optional,
typeAnnotation: wrapNullable(
nullable,
translateFunctionTypeAnnotation(
hasteModuleName,
value,
types,
aliasMap,
tryParse,
),
),
typeAnnotation: wrapNullable(nullable, translateFunctionTypeAnnotation(hasteModuleName, value, types, aliasMap, tryParse, cxxOnly, translateTypeAnnotation, language))
};

@@ -539,46 +289,21 @@ }

function isModuleInterface(node) {
return (
node.type === 'InterfaceDeclaration' &&
node.extends.length === 1 &&
node.extends[0].type === 'InterfaceExtends' &&
node.extends[0].id.name === 'TurboModule'
);
return node.type === 'InterfaceDeclaration' && node.extends.length === 1 && node.extends[0].type === 'InterfaceExtends' && node.extends[0].id.name === 'TurboModule';
}
function buildModuleSchema(
hasteModuleName ,
/**
* TODO(T71778680): Flow-type this node.
*/
ast ,
tryParse ,
) {
function buildModuleSchema(hasteModuleName,
/**
* TODO(T71778680): Flow-type this node.
*/
ast, tryParse) {
const types = getTypes(ast);
const moduleSpecs = (Object.values(types) ).filter(
isModuleInterface,
);
const moduleSpecs = Object.values(types).filter(isModuleInterface);
throwIfModuleInterfaceNotFound(moduleSpecs.length, hasteModuleName, ast, language);
throwIfMoreThanOneModuleInterfaceParserError(hasteModuleName, moduleSpecs, language);
if (moduleSpecs.length === 0) {
throw new ModuleFlowInterfaceNotFoundParserError(hasteModuleName, ast);
}
const _moduleSpecs = _slicedToArray(moduleSpecs, 1),
moduleSpec = _moduleSpecs[0];
if (moduleSpecs.length > 1) {
throw new MoreThanOneModuleFlowInterfaceParserError(
hasteModuleName,
moduleSpecs,
moduleSpecs.map(node => node.id.name),
);
}
throwIfModuleInterfaceIsMisnamed(hasteModuleName, moduleSpec.id, language); // Parse Module Names
const [moduleSpec] = moduleSpecs;
if (moduleSpec.id.name !== 'Spec') {
throw new MisnamedModuleFlowInterfaceParserError(
hasteModuleName,
moduleSpec.id,
);
}
// Parse Module Names
const moduleName = tryParse(() => {
const moduleName = tryParse(() => {
const callExpressions = [];

@@ -590,129 +315,60 @@ visit(ast, {

}
},
}
});
if (callExpressions.length === 0) {
throw new UnusedModuleFlowInterfaceParserError(
hasteModuleName,
moduleSpec,
);
}
if (callExpressions.length > 1) {
throw new MoreThanOneModuleRegistryCallsParserError(
hasteModuleName,
callExpressions,
callExpressions.length,
);
}
const [callExpression] = callExpressions;
const {typeArguments} = callExpression;
throwIfUnusedModuleInterfaceParserError(hasteModuleName, moduleSpec, callExpressions, language);
throwIfMoreThanOneModuleRegistryCalls(hasteModuleName, callExpressions, callExpressions.length, language);
const callExpression = callExpressions[0];
const typeArguments = callExpression.typeArguments;
const methodName = callExpression.callee.property.name;
throwIfWrongNumberOfCallExpressionArgs(hasteModuleName, callExpression, methodName, callExpression.arguments.length, language);
if (callExpression.arguments.length !== 1) {
throw new IncorrectModuleRegistryCallArityParserError(
hasteModuleName,
callExpression,
methodName,
callExpression.arguments.length,
);
}
if (callExpression.arguments[0].type !== 'Literal') {
const {type} = callExpression.arguments[0];
throw new IncorrectModuleRegistryCallArgumentTypeParserError(
hasteModuleName,
callExpression.arguments[0],
methodName,
type,
);
const type = callExpression.arguments[0].type;
throw new IncorrectModuleRegistryCallArgumentTypeParserError(hasteModuleName, callExpression.arguments[0], methodName, type, language);
}
const $moduleName = callExpression.arguments[0].value;
if (typeArguments == null) {
throw new UntypedModuleRegistryCallParserError(
hasteModuleName,
callExpression,
methodName,
$moduleName,
);
}
if (
typeArguments.type !== 'TypeParameterInstantiation' ||
typeArguments.params.length !== 1 ||
typeArguments.params[0].type !== 'GenericTypeAnnotation' ||
typeArguments.params[0].id.name !== 'Spec'
) {
throw new IncorrectModuleRegistryCallTypeParameterParserError(
hasteModuleName,
typeArguments,
methodName,
$moduleName,
);
}
throwIfUntypedModule(typeArguments, hasteModuleName, callExpression, methodName, $moduleName, language);
throwIfIncorrectModuleRegistryCallTypeParameterParserError(hasteModuleName, typeArguments, methodName, $moduleName, parser);
return $moduleName;
});
const moduleNames = moduleName == null ? [] : [moduleName];
// Some module names use platform suffix to indicate platform-exclusive modules.
const moduleNames = moduleName == null ? [] : [moduleName]; // Some module names use platform suffix to indicate platform-exclusive modules.
// Eventually this should be made explicit in the Flow type itself.
// Also check the hasteModuleName for platform suffix.
// Note: this shape is consistent with ComponentSchema.
const excludedPlatforms = [];
const namesToValidate = [...moduleNames, hasteModuleName];
namesToValidate.forEach(name => {
if (name.endsWith('Android')) {
excludedPlatforms.push('iOS');
} else if (name.endsWith('IOS')) {
excludedPlatforms.push('android');
}
});
// $FlowFixMe[missing-type-arg]
return (moduleSpec.body.properties )
.filter(property => property.type === 'ObjectTypeProperty')
.map
(property => {
const aliasMap = {};
const _verifyPlatforms = verifyPlatforms(hasteModuleName, moduleNames),
cxxOnly = _verifyPlatforms.cxxOnly,
excludedPlatforms = _verifyPlatforms.excludedPlatforms; // $FlowFixMe[missing-type-arg]
return tryParse(() => ({
aliasMap: aliasMap,
propertyShape: buildPropertySchema(
hasteModuleName,
property,
types,
aliasMap,
tryParse,
),
}));
})
.filter(Boolean)
.reduce(
(moduleSchema , {aliasMap, propertyShape}) => {
return {
type: 'NativeModule',
aliases: {...moduleSchema.aliases, ...aliasMap},
spec: {
properties: [...moduleSchema.spec.properties, propertyShape],
},
moduleNames: moduleSchema.moduleNames,
excludedPlatforms: moduleSchema.excludedPlatforms,
};
return moduleSpec.body.properties.filter(property => property.type === 'ObjectTypeProperty').map(property => {
const aliasMap = {};
return tryParse(() => ({
aliasMap: aliasMap,
propertyShape: buildPropertySchema(hasteModuleName, property, types, aliasMap, tryParse, cxxOnly)
}));
}).filter(Boolean).reduce((moduleSchema, {
aliasMap,
propertyShape
}) => {
return {
type: 'NativeModule',
aliases: _objectSpread({}, moduleSchema.aliases, {}, aliasMap),
spec: {
properties: [...moduleSchema.spec.properties, propertyShape]
},
{
type: 'NativeModule',
aliases: {},
spec: {properties: []},
moduleNames: moduleNames,
excludedPlatforms:
excludedPlatforms.length !== 0 ? [...excludedPlatforms] : undefined,
},
);
moduleNames: moduleSchema.moduleNames,
excludedPlatforms: moduleSchema.excludedPlatforms
};
}, {
type: 'NativeModule',
aliases: {},
spec: {
properties: []
},
moduleNames: moduleNames,
excludedPlatforms: excludedPlatforms.length !== 0 ? [...excludedPlatforms] : undefined
});
}

@@ -722,2 +378,3 @@

buildModuleSchema,
};
flowTranslateTypeAnnotation: translateTypeAnnotation
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,7 +10,3 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
const {ParserError} = require('./errors');
/**

@@ -24,55 +20,29 @@ * This FlowFixMe is supposed to refer to an InterfaceDeclaration or TypeAlias

*/
function getTypes(ast ) {
function getTypes(ast) {
return ast.body.reduce((types, node) => {
if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') {
if (
node.declaration.type === 'TypeAlias' ||
node.declaration.type === 'InterfaceDeclaration'
) {
if (node.declaration != null && (node.declaration.type === 'TypeAlias' || node.declaration.type === 'InterfaceDeclaration')) {
types[node.declaration.id.name] = node.declaration;
}
} else if (
node.type === 'TypeAlias' ||
node.type === 'InterfaceDeclaration'
) {
} else if (node.type === 'ExportNamedDeclaration' && node.exportKind === 'value' && node.declaration && node.declaration.type === 'EnumDeclaration') {
types[node.declaration.id.name] = node.declaration;
} else if (node.type === 'TypeAlias' || node.type === 'InterfaceDeclaration' || node.type === 'EnumDeclaration') {
types[node.id.name] = node;
}
return types;
}, {});
}
} // $FlowFixMe[unclear-type] there's no flowtype for ASTs
// $FlowFixMe[unclear-type] there's no flowtype for ASTs
const invariant = require('invariant');
function resolveTypeAnnotation(
// TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this
typeAnnotation ,
types ,
)
{
invariant(
typeAnnotation != null,
'resolveTypeAnnotation(): typeAnnotation cannot be null',
);
function resolveTypeAnnotation( // TODO(T71778680): This is an Flow TypeAnnotation. Flow-type this
typeAnnotation, types) {
invariant(typeAnnotation != null, 'resolveTypeAnnotation(): typeAnnotation cannot be null');
let node = typeAnnotation;
let nullable = false;
let typeAliasResolutionStatus = {
successful: false,
let typeAliasResolutionStatus = {
successful: false
};

@@ -87,14 +57,11 @@

successful: true,
aliasName: node.id.name,
aliasName: node.id.name
};
const resolvedTypeAnnotation = types[node.id.name];
if (resolvedTypeAnnotation == null) {
if (resolvedTypeAnnotation == null || resolvedTypeAnnotation.type === 'EnumDeclaration') {
break;
}
invariant(
resolvedTypeAnnotation.type === 'TypeAlias',
`GenericTypeAnnotation '${node.id.name}' must resolve to a TypeAlias. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`,
);
invariant(resolvedTypeAnnotation.type === 'TypeAlias', `GenericTypeAnnotation '${node.id.name}' must resolve to a TypeAlias. Instead, it resolved to a '${resolvedTypeAnnotation.type}'`);
node = resolvedTypeAnnotation.right;

@@ -109,106 +76,18 @@ } else {

typeAnnotation: node,
typeAliasResolutionStatus,
typeAliasResolutionStatus
};
}
function getValueFromTypes(value , types ) {
function getValueFromTypes(value, types) {
if (value.type === 'GenericTypeAnnotation' && types[value.id.name]) {
return getValueFromTypes(types[value.id.name].right, types);
}
return value;
}
function createParserErrorCapturer()
{
const errors = [];
function guard (fn ) {
try {
return fn();
} catch (error) {
if (!(error instanceof ParserError)) {
throw error;
}
errors.push(error);
return null;
}
}
return [errors, guard];
}
// TODO(T71778680): Flow-type ASTNodes.
function visit(
astNode ,
visitor
,
) {
const queue = [astNode];
while (queue.length !== 0) {
let item = queue.shift();
if (!(typeof item === 'object' && item != null)) {
continue;
}
if (
typeof item.type === 'string' &&
typeof visitor[item.type] === 'function'
) {
// Don't visit any children
visitor[item.type](item);
} else if (Array.isArray(item)) {
queue.push(...item);
} else {
queue.push(...Object.values(item));
}
}
}
// TODO(T71778680): Flow-type ASTNodes.
function isModuleRegistryCall(node ) {
if (node.type !== 'CallExpression') {
return false;
}
const callExpression = node;
if (callExpression.callee.type !== 'MemberExpression') {
return false;
}
const memberExpression = callExpression.callee;
if (
!(
memberExpression.object.type === 'Identifier' &&
memberExpression.object.name === 'TurboModuleRegistry'
)
) {
return false;
}
if (
!(
memberExpression.property.type === 'Identifier' &&
(memberExpression.property.name === 'get' ||
memberExpression.property.name === 'getEnforcing')
)
) {
return false;
}
return true;
}
module.exports = {
getValueFromTypes,
resolveTypeAnnotation,
createParserErrorCapturer,
getTypes,
visit,
isModuleRegistryCall,
};
getTypes
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,13 +10,9 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';
function parse(filename ) {
function parse(filename) {
try {
// $FlowFixMe[unsupported-syntax] Can't require dynamic variables
return require(filename);
} catch (err) {
// Ignore
} catch (err) {// Ignore
}

@@ -26,3 +22,3 @@ }

module.exports = {
parse,
};
parse
};
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* Copyright (c) Meta Platforms, Inc. and affiliates.
*

@@ -10,3 +10,2 @@ * This source code is licensed under the MIT license found in the

*/
'use strict';

@@ -16,10 +15,6 @@

function getErrors(schema) {
const errors = new Set(); // Map of component name -> Array of module names
function getErrors(schema ) {
const errors = new Set();
// Map of component name -> Array of module names
const componentModules = new Map();
const componentModules = new Map();
Object.keys(schema.modules).forEach(moduleName => {

@@ -44,17 +39,11 @@ const module = schema.modules[moduleName];

});
componentModules.forEach((modules, componentName) => {
if (modules.length > 1) {
errors.add(
`Duplicate components found with name ${componentName}. Found in modules ${modules.join(
', ',
)}`,
);
errors.add(`Duplicate components found with name ${componentName}. Found in modules ${modules.join(', ')}`);
}
});
return Array.from(errors).sort();
}
function validate(schema ) {
function validate(schema) {
const errors = getErrors(schema);

@@ -69,3 +58,3 @@

getErrors,
validate,
};
validate
};
{
"name": "react-native-tscodegen",
"version": "0.68.5",
"version": "0.71.0",
"description": "TypeScript Code Generation for React Native Turbo Module",
"main": "./lib/index.js",
"bin": "./bin/cli",
"typings": "./lib/index.d.ts",
"scripts": {
"build": "flow-remove-types ../../react-native/packages/react-native-codegen/ -q -d lib/rncodegen/ & tslint --project tsconfig.json & tsc"
"clean-flow": "rimraf lib/rncodegen",
"build-flow": "flow-remove-types ../../react-native/packages/react-native-codegen/ -q -d lib/rncodegen/",
"fix-flow": "babel lib/rncodegen/ -d lib/rncodegen",
"patch-rncodegen": "node ./patch-rncodegen.js",
"build-ts": "tslint --project tsconfig.json & tsc",
"build": "npm run clean-flow & npm run build-flow & npm run fix-flow & npm run patch-rncodegen & npm run build-ts"
},

@@ -25,9 +29,30 @@ "repository": {

"tslint-microsoft-contrib": "^6.2.0",
"@react-native-tscodegen/tslint-shared": "^1.0.0"
"rimraf": "3.0.2",
"@react-native-tscodegen/tslint-shared": "^1.0.0",
"@babel/cli": "7.18.10",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-proposal-optional-chaining": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-transform-async-to-generator": "^7.0.0",
"@babel/plugin-transform-destructuring": "^7.0.0",
"@babel/plugin-transform-flow-strip-types": "^7.0.0"
},
"dependencies": {
"typescript": "^4.1.5",
"jscodeshift": "0.6.4",
"nullthrows": "1.1.1"
},
"babel": {
"plugins": [
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-transform-async-to-generator",
"@babel/plugin-transform-destructuring",
"@babel/plugin-transform-flow-strip-types",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining"
]
}
}

@@ -7,3 +7,3 @@ # Welcome to react-native-tscodegen (beta)!

0.65-stable
0.70.1

@@ -47,4 +47,4 @@ ## Authoring a Turbo Module

"shadow-nodes",
"modulesAndroid"
"modulesCxx"
"modulesAndroid",
"modulesCxx",
"modulesIOS"

@@ -51,0 +51,0 @@ ],

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc