Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "Initial react-native-windows-codegen",
"packageName": "react-native-windows-codegen",
"email": "acoates@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-22T20:49:54.580Z"
}
32 changes: 32 additions & 0 deletions packages/microsoft-reactnative-sampleapps/NativeMyModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @flow
* @format
*/

'use strict';

import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry';

export interface Spec extends TurboModule {
// Exported methods.
+getConstants: () => {|
const1: boolean,
const2: number,
const3: string,
|};
+voidFunc: () => void;
+getBool: (arg: boolean) => boolean;
+getNumber: (arg: number) => number;
+getString: (arg: string) => string;
+getArray: (arg: Array<any>) => Array<any>;
+getObject: (arg: Object) => Object;
+getValue: (x: number, y: string, z: Object) => Object;
+getValueWithCallback: (callback: (value: string) => void) => void;
+getValueWithPromise: (error: boolean) => Promise<string>;
}

export default (TurboModuleRegistry.getEnforcing<Spec>('MyModule'): Spec);
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@

/**
* This file is auto-generated from a NativeModule spec file in js.
*/

#pragma once

#include "NativeModules.h"
#include <tuple>

namespace SampleLibraryCpp {

/*
* This is a C++ Spec class that should be used with MakeTurboModuleProvider to register native modules
* in a way that also verifies at compile time that the native module matches the interface required
* by the TurboModule JS spec.
*/
struct MyModuleSpec : winrt::Microsoft::ReactNative::TurboModuleSpec {
static constexpr auto methods = std::tuple{
Method<void() noexcept>{0, L"voidFunc"},
SyncMethod<bool(bool) noexcept>{1, L"getBool"},
SyncMethod<double(double) noexcept>{2, L"getNumber"},
SyncMethod<std::string(std::string) noexcept>{3, L"getString"},
SyncMethod<JSValueArray(JSValueArray) noexcept>{4, L"getArray"},
SyncMethod<JSValueObject(JSValueObject) noexcept>{5, L"getObject"},
SyncMethod<JSValueObject(double,std::string,JSValueObject) noexcept>{6, L"getValue"},
Method<void(Callback<JSValue>) noexcept>{7, L"getValueWithCallback"},
Method<void(bool,Promise<JSValue>) noexcept>{8, L"getValueWithPromise"},
};

template <class TModule>
static constexpr void ValidateModule() noexcept {
constexpr auto methodCheckResults = CheckMethods<TModule, MyModuleSpec>();

REACT_SHOW_METHOD_SPEC_ERRORS(
0,
"voidFunc",
" REACT_METHOD(voidFunc) void voidFunc() noexcept { /* implementation */ }}",
" REACT_METHOD(voidFunc) static void voidFunc() noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
1,
"getBool",
" REACT_SYNC_METHOD(getBool) bool getBool(bool arg) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getBool) static bool getBool(bool arg) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
2,
"getNumber",
" REACT_SYNC_METHOD(getNumber) double getNumber(double arg) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getNumber) static double getNumber(double arg) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
3,
"getString",
" REACT_SYNC_METHOD(getString) std::string getString(std::string arg) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getString) static std::string getString(std::string arg) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
4,
"getArray",
" REACT_SYNC_METHOD(getArray) React::JSValueArray getArray(React::JSValueArray && arg) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getArray) static React::JSValueArray getArray(React::JSValueArray && arg) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
5,
"getObject",
" REACT_SYNC_METHOD(getObject) React::JSValueObject getObject(React::JSValueObject && arg) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getObject) static React::JSValueObject getObject(React::JSValueObject && arg) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
6,
"getValue",
" REACT_SYNC_METHOD(getValue) React::JSValueObject getValue(double x, std::string y, React::JSValueObject && z) noexcept { /* implementation */ }}",
" REACT_SYNC_METHOD(getValue) static React::JSValueObject getValue(double x, std::string y, React::JSValueObject && z) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
7,
"getValueWithCallback",
" REACT_METHOD(getValueWithCallback) void getValueWithCallback(std::function<void(React::JSValue const &)> const & callback) noexcept { /* implementation */ }}",
" REACT_METHOD(getValueWithCallback) static void getValueWithCallback(std::function<void(React::JSValue const &)> const & callback) noexcept { /* implementation */ }}");
REACT_SHOW_METHOD_SPEC_ERRORS(
8,
"getValueWithPromise",
" REACT_METHOD(getValueWithPromise) void getValueWithPromise(bool error, React::ReactPromise<React::JSValue> &&result) noexcept { /* implementation */ }}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

void [](start = 49, length = 4)

I think we are missing here a version with winrt::fire_and_forget

" REACT_METHOD(getValueWithPromise) static void getValueWithPromise(bool error, React::ReactPromise<React::JSValue> &&result) noexcept { /* implementation */ }}");
}
};

} // namespace SampleLibraryCpp
4 changes: 4 additions & 0 deletions packages/microsoft-reactnative-sampleapps/index.windows.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { NativeModules, NativeEventEmitter } from 'react-native';

import {MyComp} from './myComp';

import {default as MyModule} from './NativeMyModule';

// Creating event emitters
const SampleModuleCSEmitter = new NativeEventEmitter(NativeModules.SampleModuleCS);
const SampleModuleCppEmitter = new NativeEventEmitter(NativeModules.SampleModuleCpp);
Expand Down Expand Up @@ -278,6 +280,8 @@ class SampleApp extends Component {
This app consumes custom Native Modules and View Managers.
</Text>

<Button onPress={() => { MyModule.voidFunc(); }} title="Call MyModule tests"/>

<Button onPress={() => { this.onPressSampleModuleCS(); }} title="Call SampleModuleCS!" disabled={NativeModules.SampleModuleCS == null} />
<Button onPress={() => { this.onPressSampleModuleCpp(); }} title="Call SampleModuleCpp!" disabled={NativeModules.SampleModuleCpp == null} />

Expand Down
10 changes: 9 additions & 1 deletion packages/microsoft-reactnative-sampleapps/just-task.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
const {
task,
series,
parallel,
option,
argv,
tscTask,
eslintTask,
} = require('just-scripts');
const fs = require('fs');
const path = require('path');
const {execSync} = require('child_process');

option('production');
option('clean');
Expand All @@ -36,6 +38,12 @@ task('ts', () => {
});
});

task('codegen', () => {
execSync(
'npx react-native-windows-codegen --file NativeMyModule.js --namespace SampleLibraryCpp',
);
});

function ensureDirectoryExists(filePath) {
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) {
Expand All @@ -49,6 +57,6 @@ task('prepareBundle', () => {
ensureDirectoryExists('windows/SampleAppCPP/Bundle');
});

task('build', series('ts'));
task('build', parallel('ts', 'codegen'));
task('lint', series('eslint'));
task('lint:fix', series('eslint:fix'));
1 change: 1 addition & 0 deletions packages/microsoft-reactnative-sampleapps/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@types/react-native": "^0.62.2",
"just-scripts": "^0.36.1",
"metro-react-native-babel-preset": "^0.56.0",
"react-native-windows-codegen": "0.0.1",
"react-test-renderer": "16.9.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include "DebugHelpers.h"

#define DEBUG_MYMODULE_OUTPUT(...) DebugWriteLine("MyModule", ##__VA_ARGS__);

namespace SampleLibraryCpp {

REACT_MODULE(MyModule)
struct MyModule {
// The spec file does not currently validate constants
REACT_CONSTANT(const1)
const bool const1 = true;
REACT_CONSTANT(const2)
const double const2 = 1.234;
REACT_CONSTANT(const3)
const std::string const3{"const3"};

REACT_METHOD(voidFunc)
void voidFunc() noexcept {
DEBUG_MYMODULE_OUTPUT("voidFunc");
}

REACT_SYNC_METHOD(getBool)
bool getBool(bool arg) noexcept {
DEBUG_MYMODULE_OUTPUT("getBool", arg);
return arg;
}

REACT_SYNC_METHOD(getNumber)
double getNumber(double arg) noexcept {
DEBUG_MYMODULE_OUTPUT("getNumber", arg);
return arg;
}

REACT_SYNC_METHOD(getString)
std::string getString(std::string arg) noexcept {
DEBUG_MYMODULE_OUTPUT("getString", arg);
return arg;
}

REACT_SYNC_METHOD(getArray)
React::JSValueArray getArray(React::JSValueArray && /*arg*/) noexcept {
return React::JSValueArray{"X", 4, true};
}

REACT_SYNC_METHOD(getObject)
React::JSValueObject getObject(React::JSValueObject && /*arg*/) noexcept {
return React::JSValueObject{{"X", 4}, {"Y", 2}};
}

REACT_SYNC_METHOD(getValue)
React::JSValueObject getValue(double x, std::string y, JSValueObject &&z) noexcept {
return React::JSValueObject{{"X", x}, {"Y", y}, {"Z", std::move(z)}};
}

REACT_METHOD(getValueWithCallback)
void getValueWithCallback(std::function<void(React::JSValue const &)> const &callback) noexcept {
callback(React::JSValue{"some string"});
}

REACT_METHOD(getValueWithPromise)
void getValueWithPromise(bool error, React::ReactPromise<React::JSValue> &&result) noexcept {
if (error) {
result.Reject("Failure");
} else {
result.Resolve(React::JSValue{"Succeeded"});
}
}
};

} // namespace SampleLibraryCpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,21 @@
#include "CustomUserControlViewManagerCpp.h"
#include "SampleModuleCpp.h"

// Import generated definitions
#include "..\..\codegen\NativeModules.g.h"

// Import impls of modules
#include "MyModule.h"

using namespace winrt::Microsoft::ReactNative;

namespace winrt::SampleLibraryCpp::implementation {

void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept {
AddAttributedModules(packageBuilder);

packageBuilder.AddModule(
L"MyModule", MakeTurboModuleProvider<::SampleLibraryCpp::MyModule, ::SampleLibraryCpp::MyModuleSpec>());
packageBuilder.AddViewManager(
L"CustomUserControlViewManagerCpp", []() { return winrt::make<CustomUserControlViewManagerCpp>(); });
packageBuilder.AddViewManager(L"CircleViewManagerCpp", []() { return winrt::make<CircleViewManagerCpp>(); });
Expand Down
2 changes: 2 additions & 0 deletions packages/react-native-windows-codegen/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lib/
lib-commonjs/
7 changes: 7 additions & 0 deletions packages/react-native-windows-codegen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# react-native-windows-codegen

Generators for react-native-codegen targeting react-native-windows

## Usage

Coming soon..
12 changes: 12 additions & 0 deletions packages/react-native-windows-codegen/bin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env node

/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @format
*/

// Yarn will fail to link workspace binaries if they haven't been built yet. Add
// a simple JS file to forward to the CLI which is built after install.
require('./lib-commonjs/Cli');
20 changes: 20 additions & 0 deletions packages/react-native-windows-codegen/just-task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT License.
*
* @format
* @ts-check
*/

const {eslintTask, series, task, taskPresets} = require('just-scripts');

taskPresets.lib();

task('eslint', () => {
return eslintTask();
});
task('eslint:fix', () => {
return eslintTask({fix: true});
});
task('lint', series('eslint'));
task('lint:fix', series('eslint:fix'));
29 changes: 29 additions & 0 deletions packages/react-native-windows-codegen/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "react-native-windows-codegen",
"version": "0.0.1",
"description": "Generators for react-native-codegen targeting react-native-windows",
"main": "index.js",
"repository": "https://github.com/microsoft/react-native-windows",
"license": "MIT",
"private": false,
"scripts": {
"build": "just-scripts build",
"clean": "just-scripts clean",
"lint": "just-scripts lint",
"lint:fix": "just-scripts lint:fix"
},
"bin": {
"react-native-windows-codegen": "./bin.js"
},
"dependencies": {
"chalk": "^3",
"react-native-tscodegen": "0.0.10",
"react-native-codegen": "0.0.2",
"yargs": "^15.1.0"
},
"devDependencies": {
"@types/chalk": "^2.2.0",
"@types/yargs": "^15.0.3",
"just-scripts": "^0.36.1"
}
}
Loading