nitrogen 0.2.24 → 0.29.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -108
- package/lib/Logger.js +56 -0
- package/lib/autolinking/Autolinking.js +1 -0
- package/lib/autolinking/android/createCMakeExtension.js +109 -0
- package/lib/autolinking/android/createGradleExtension.js +36 -0
- package/lib/autolinking/android/createHybridObjectInitializer.js +159 -0
- package/lib/autolinking/createAndroidAutolinking.js +13 -0
- package/lib/autolinking/createIOSAutolinking.js +19 -0
- package/lib/autolinking/ios/createHybridObjectInitializer.js +97 -0
- package/lib/autolinking/ios/createPodspecRubyExtension.js +69 -0
- package/lib/autolinking/ios/createSwiftCxxBridge.js +117 -0
- package/lib/autolinking/ios/createSwiftUmbrellaHeader.js +74 -0
- package/lib/config/NitroConfig.js +112 -0
- package/lib/config/NitroUserConfig.js +88 -0
- package/lib/config/getConfig.js +84 -0
- package/lib/createGitAttributes.js +11 -0
- package/lib/createPlatformSpec.js +127 -0
- package/lib/getFiles.js +28 -0
- package/lib/getPlatformSpecs.js +153 -0
- package/lib/index.js +113 -10
- package/lib/init.js +123 -0
- package/lib/nitrogen.js +165 -0
- package/lib/prettifyDirectory.js +27 -0
- package/lib/syntax/BridgedType.js +1 -0
- package/lib/syntax/CodeNode.js +1 -0
- package/lib/syntax/HybridObjectSpec.js +1 -0
- package/lib/syntax/Method.js +108 -0
- package/lib/syntax/Parameter.js +65 -0
- package/lib/syntax/Property.js +147 -0
- package/lib/syntax/SourceFile.js +7 -0
- package/lib/syntax/c++/CppEnum.js +110 -0
- package/lib/syntax/c++/CppHybridObject.js +146 -0
- package/lib/syntax/c++/CppHybridObjectRegistration.js +18 -0
- package/lib/syntax/c++/CppStruct.js +108 -0
- package/lib/syntax/c++/CppUnion.js +88 -0
- package/lib/syntax/c++/getForwardDeclaration.js +14 -0
- package/lib/syntax/c++/includeNitroHeader.js +34 -0
- package/lib/syntax/createType.js +303 -0
- package/lib/syntax/getAllTypes.js +11 -0
- package/lib/syntax/getCustomTypeConfig.js +53 -0
- package/lib/syntax/getHybridObjectName.d.ts +36 -0
- package/lib/syntax/getHybridObjectName.js +10 -0
- package/lib/syntax/getInterfaceProperties.js +9 -0
- package/lib/syntax/getReferencedTypes.js +47 -0
- package/lib/syntax/helpers.js +53 -0
- package/lib/syntax/isCoreType.js +47 -0
- package/lib/syntax/kotlin/FbjniHybridObject.js +261 -0
- package/lib/syntax/kotlin/JNINativeRegistrations.js +7 -0
- package/lib/syntax/kotlin/KotlinBoxedPrimitive.js +17 -0
- package/lib/syntax/kotlin/KotlinCxxBridgedType.js +893 -0
- package/lib/syntax/kotlin/KotlinEnum.js +113 -0
- package/lib/syntax/kotlin/KotlinFunction.js +256 -0
- package/lib/syntax/kotlin/KotlinHybridObject.js +177 -0
- package/lib/syntax/kotlin/KotlinHybridObjectRegistration.js +26 -0
- package/lib/syntax/kotlin/KotlinStruct.js +172 -0
- package/lib/syntax/kotlin/KotlinVariant.js +191 -0
- package/lib/syntax/swift/SwiftCxxBridgedType.js +819 -0
- package/lib/syntax/swift/SwiftCxxTypeHelper.js +613 -0
- package/lib/syntax/swift/SwiftEnum.js +52 -0
- package/lib/syntax/swift/SwiftFunction.js +83 -0
- package/lib/syntax/swift/SwiftHybridObject.js +103 -0
- package/lib/syntax/swift/SwiftHybridObjectBridge.js +451 -0
- package/lib/syntax/swift/SwiftHybridObjectRegistration.js +42 -0
- package/lib/syntax/swift/SwiftStruct.js +75 -0
- package/lib/syntax/swift/SwiftVariant.js +58 -0
- package/lib/syntax/types/ArrayBufferType.js +37 -0
- package/lib/syntax/types/ArrayType.d.ts +12 -0
- package/lib/syntax/types/ArrayType.js +52 -0
- package/lib/syntax/types/BigIntType.js +27 -0
- package/lib/syntax/types/BooleanType.js +27 -0
- package/lib/syntax/types/CustomType.d.ts +14 -0
- package/lib/syntax/types/CustomType.js +36 -0
- package/lib/syntax/types/DateType.js +35 -0
- package/lib/syntax/types/EnumType.js +101 -0
- package/lib/syntax/types/ErrorType.js +37 -0
- package/lib/syntax/types/FunctionType.js +147 -0
- package/lib/syntax/types/HybridObjectBaseType.js +38 -0
- package/lib/syntax/types/HybridObjectType.js +131 -0
- package/lib/syntax/types/MapType.js +37 -0
- package/lib/syntax/types/NamedWrappingType.js +27 -0
- package/lib/syntax/types/NullType.js +23 -0
- package/lib/syntax/types/NumberType.js +27 -0
- package/lib/syntax/types/OptionalType.js +59 -0
- package/lib/syntax/types/PromiseType.js +62 -0
- package/lib/syntax/types/RecordType.js +47 -0
- package/lib/syntax/types/ResultWrappingType.js +44 -0
- package/lib/syntax/types/StringType.js +35 -0
- package/lib/syntax/types/StructType.js +61 -0
- package/lib/syntax/types/TupleType.js +39 -0
- package/lib/syntax/types/Type.js +1 -0
- package/lib/syntax/types/VariantType.js +75 -0
- package/lib/syntax/types/VoidType.js +27 -0
- package/lib/syntax/types/getTypeAs.js +12 -0
- package/lib/utils.js +126 -0
- package/lib/views/CppHybridViewComponent.js +256 -0
- package/lib/views/createHostComponentJs.js +27 -0
- package/lib/views/kotlin/KotlinHybridViewManager.js +229 -0
- package/lib/views/swift/SwiftHybridViewManager.js +131 -0
- package/lib/writeFile.js +19 -0
- package/package.json +58 -29
- package/src/Logger.ts +63 -0
- package/src/autolinking/Autolinking.ts +9 -0
- package/src/autolinking/android/createCMakeExtension.ts +126 -0
- package/src/autolinking/android/createGradleExtension.ts +43 -0
- package/src/autolinking/android/createHybridObjectInitializer.ts +174 -0
- package/src/autolinking/createAndroidAutolinking.ts +28 -0
- package/src/autolinking/createIOSAutolinking.ts +24 -0
- package/src/autolinking/ios/createHybridObjectInitializer.ts +112 -0
- package/src/autolinking/ios/createPodspecRubyExtension.ts +76 -0
- package/src/autolinking/ios/createSwiftCxxBridge.ts +137 -0
- package/src/autolinking/ios/createSwiftUmbrellaHeader.ts +90 -0
- package/src/config/NitroConfig.ts +139 -0
- package/src/config/NitroUserConfig.ts +105 -0
- package/src/config/getConfig.ts +91 -0
- package/src/createGitAttributes.ts +15 -0
- package/src/createPlatformSpec.ts +176 -0
- package/src/getFiles.ts +31 -0
- package/src/getPlatformSpecs.ts +202 -0
- package/src/index.ts +146 -0
- package/src/init.ts +186 -0
- package/src/nitrogen.ts +246 -0
- package/src/prettifyDirectory.ts +32 -0
- package/src/syntax/BridgedType.ts +59 -0
- package/src/syntax/CodeNode.ts +24 -0
- package/src/syntax/HybridObjectSpec.ts +14 -0
- package/src/syntax/Method.ts +154 -0
- package/src/syntax/Parameter.ts +81 -0
- package/src/syntax/Property.ts +203 -0
- package/src/syntax/SourceFile.ts +80 -0
- package/src/syntax/c++/CppEnum.ts +128 -0
- package/src/syntax/c++/CppHybridObject.ts +165 -0
- package/src/syntax/c++/CppHybridObjectRegistration.ts +39 -0
- package/src/syntax/c++/CppStruct.ts +129 -0
- package/src/syntax/c++/CppUnion.ts +105 -0
- package/src/syntax/c++/getForwardDeclaration.ts +19 -0
- package/src/syntax/c++/includeNitroHeader.ts +40 -0
- package/src/syntax/createType.ts +365 -0
- package/src/syntax/getAllTypes.ts +18 -0
- package/src/syntax/getCustomTypeConfig.ts +71 -0
- package/src/syntax/getHybridObjectName.ts +48 -0
- package/src/syntax/getInterfaceProperties.ts +21 -0
- package/src/syntax/getReferencedTypes.ts +57 -0
- package/src/syntax/helpers.ts +79 -0
- package/src/syntax/isCoreType.ts +60 -0
- package/src/syntax/kotlin/FbjniHybridObject.ts +313 -0
- package/src/syntax/kotlin/JNINativeRegistrations.ts +19 -0
- package/src/syntax/kotlin/KotlinBoxedPrimitive.ts +19 -0
- package/src/syntax/kotlin/KotlinCxxBridgedType.ts +942 -0
- package/src/syntax/kotlin/KotlinEnum.ts +130 -0
- package/src/syntax/kotlin/KotlinFunction.ts +277 -0
- package/src/syntax/kotlin/KotlinHybridObject.ts +205 -0
- package/src/syntax/kotlin/KotlinHybridObjectRegistration.ts +51 -0
- package/src/syntax/kotlin/KotlinStruct.ts +198 -0
- package/src/syntax/kotlin/KotlinVariant.ts +212 -0
- package/src/syntax/swift/SwiftCxxBridgedType.ts +874 -0
- package/src/syntax/swift/SwiftCxxTypeHelper.ts +674 -0
- package/src/syntax/swift/SwiftEnum.ts +65 -0
- package/src/syntax/swift/SwiftFunction.ts +91 -0
- package/src/syntax/swift/SwiftHybridObject.ts +121 -0
- package/src/syntax/swift/SwiftHybridObjectBridge.ts +522 -0
- package/src/syntax/swift/SwiftHybridObjectRegistration.ts +75 -0
- package/src/syntax/swift/SwiftStruct.ts +85 -0
- package/src/syntax/swift/SwiftVariant.ts +67 -0
- package/src/syntax/types/ArrayBufferType.ts +49 -0
- package/src/syntax/types/ArrayType.ts +62 -0
- package/src/syntax/types/BigIntType.ts +35 -0
- package/src/syntax/types/BooleanType.ts +35 -0
- package/src/syntax/types/CustomType.ts +47 -0
- package/src/syntax/types/DateType.ts +43 -0
- package/src/syntax/types/EnumType.ts +130 -0
- package/src/syntax/types/ErrorType.ts +44 -0
- package/src/syntax/types/FunctionType.ts +167 -0
- package/src/syntax/types/HybridObjectBaseType.ts +54 -0
- package/src/syntax/types/HybridObjectType.ts +198 -0
- package/src/syntax/types/MapType.ts +49 -0
- package/src/syntax/types/NamedWrappingType.ts +33 -0
- package/src/syntax/types/NullType.ts +30 -0
- package/src/syntax/types/NumberType.ts +34 -0
- package/src/syntax/types/OptionalType.ts +66 -0
- package/src/syntax/types/PromiseType.ts +72 -0
- package/src/syntax/types/RecordType.ts +56 -0
- package/src/syntax/types/ResultWrappingType.ts +53 -0
- package/src/syntax/types/StringType.ts +44 -0
- package/src/syntax/types/StructType.ts +83 -0
- package/src/syntax/types/TupleType.ts +53 -0
- package/src/syntax/types/Type.ts +82 -0
- package/src/syntax/types/VariantType.ts +92 -0
- package/src/syntax/types/VoidType.ts +34 -0
- package/src/syntax/types/getTypeAs.ts +15 -0
- package/src/utils.ts +162 -0
- package/src/views/CppHybridViewComponent.ts +304 -0
- package/src/views/createHostComponentJs.ts +34 -0
- package/src/views/kotlin/KotlinHybridViewManager.ts +258 -0
- package/src/views/swift/SwiftHybridViewManager.ts +153 -0
- package/src/writeFile.ts +27 -0
- package/.jshintignore +0 -6
- package/.jshintrc +0 -3
- package/.npmignore +0 -3
- package/.travis.yml +0 -13
- package/LICENSE +0 -13
- package/browser/nitrogen-min.js +0 -3
- package/browser/nitrogen.js +0 -6369
- package/lib/apiKey.js +0 -67
- package/lib/blob.js +0 -57
- package/lib/commandManager.js +0 -350
- package/lib/device.js +0 -19
- package/lib/memoryStore.js +0 -24
- package/lib/message.js +0 -298
- package/lib/permission.js +0 -121
- package/lib/principal.js +0 -330
- package/lib/service.js +0 -347
- package/lib/session.js +0 -494
- package/lib/user.js +0 -20
- package/publish +0 -2
- package/scripts/build-documentation +0 -4
- package/scripts/build-module +0 -27
- package/scripts/module.js +0 -12
- package/scripts/postamble.js +0 -1
- package/scripts/preamble.js +0 -2
- package/scripts/run-test-server +0 -9
- package/test/config.js +0 -12
- package/test/fixtures/images/image.jpg +0 -0
- package/test/fixtures/images/motion0.jpg +0 -0
- package/test/fixtures/images/motion1.jpg +0 -0
- package/test/fixtures/images/motion2.jpg +0 -0
- package/test/fixtures/index.js +0 -76
- package/test/main.js +0 -5
- package/test/memoryStore.js +0 -22
- package/test/mocha.opts +0 -3
- package/test/units/apiKey.js +0 -46
- package/test/units/blob.js +0 -35
- package/test/units/commandManager.js +0 -67
- package/test/units/device.js +0 -26
- package/test/units/heartbeat.js +0 -28
- package/test/units/message.js +0 -79
- package/test/units/permissions.js +0 -43
- package/test/units/principal.js +0 -116
- package/test/units/service.js +0 -92
- package/test/units/session.js +0 -97
- package/test/units/user.js +0 -48
- package/yuidoc.json +0 -8
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { escapeCppName, isNotDuplicate } from '../helpers.js';
|
|
2
|
+
import {} from '../SourceFile.js';
|
|
3
|
+
export const VariantLabels = [
|
|
4
|
+
'first',
|
|
5
|
+
'second',
|
|
6
|
+
'third',
|
|
7
|
+
'fourth',
|
|
8
|
+
'fifth',
|
|
9
|
+
'sixth',
|
|
10
|
+
'seventh',
|
|
11
|
+
'eigth',
|
|
12
|
+
'ninth',
|
|
13
|
+
'tenth',
|
|
14
|
+
];
|
|
15
|
+
export class VariantType {
|
|
16
|
+
variants;
|
|
17
|
+
aliasName;
|
|
18
|
+
constructor(variants, aliasName) {
|
|
19
|
+
this.variants = variants;
|
|
20
|
+
this.aliasName = aliasName;
|
|
21
|
+
}
|
|
22
|
+
get canBePassedByReference() {
|
|
23
|
+
// It's a variant<..> - heavy to copy
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
get kind() {
|
|
27
|
+
return 'variant';
|
|
28
|
+
}
|
|
29
|
+
get jsType() {
|
|
30
|
+
return this.variants.map((v) => v.kind).join(' | ');
|
|
31
|
+
}
|
|
32
|
+
get cases() {
|
|
33
|
+
return this.variants.map((v, i) => {
|
|
34
|
+
const label = VariantLabels[i];
|
|
35
|
+
if (label == null)
|
|
36
|
+
throw new Error(`Variant<...> (\`${this.jsType}\`) does not support ${i} cases!`);
|
|
37
|
+
return [label, v];
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
getAliasName(language, options) {
|
|
41
|
+
if (this.aliasName == null) {
|
|
42
|
+
const variants = this.variants.map((v) => v.getCode(language, options));
|
|
43
|
+
return escapeCppName(`Variant_${variants.join('_')}`);
|
|
44
|
+
}
|
|
45
|
+
return this.aliasName;
|
|
46
|
+
}
|
|
47
|
+
getCode(language, options) {
|
|
48
|
+
const types = this.variants
|
|
49
|
+
.map((v) => v.getCode(language, options))
|
|
50
|
+
.filter(isNotDuplicate);
|
|
51
|
+
switch (language) {
|
|
52
|
+
case 'c++':
|
|
53
|
+
return `std::variant<${types.join(', ')}>`;
|
|
54
|
+
case 'swift':
|
|
55
|
+
case 'kotlin':
|
|
56
|
+
return this.getAliasName(language, options);
|
|
57
|
+
default:
|
|
58
|
+
throw new Error(`Language ${language} is not yet supported for VariantType!`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
getExtraFiles() {
|
|
62
|
+
return this.variants.flatMap((v) => v.getExtraFiles());
|
|
63
|
+
}
|
|
64
|
+
getRequiredImports(language) {
|
|
65
|
+
const imports = this.variants.flatMap((v) => v.getRequiredImports(language));
|
|
66
|
+
if (language === 'c++') {
|
|
67
|
+
imports.push({
|
|
68
|
+
language: 'c++',
|
|
69
|
+
name: 'variant',
|
|
70
|
+
space: 'system',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return imports;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export class VoidType {
|
|
2
|
+
get canBePassedByReference() {
|
|
3
|
+
// It's void.
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
get kind() {
|
|
7
|
+
return 'void';
|
|
8
|
+
}
|
|
9
|
+
getCode(language) {
|
|
10
|
+
switch (language) {
|
|
11
|
+
case 'c++':
|
|
12
|
+
return 'void';
|
|
13
|
+
case 'swift':
|
|
14
|
+
return 'Void';
|
|
15
|
+
case 'kotlin':
|
|
16
|
+
return 'Unit';
|
|
17
|
+
default:
|
|
18
|
+
throw new Error(`Language ${language} is not yet supported for VoidType!`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
getExtraFiles() {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
getRequiredImports() {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { NamedWrappingType } from './NamedWrappingType.js';
|
|
2
|
+
export function getTypeAs(type, classReference) {
|
|
3
|
+
if (type instanceof classReference) {
|
|
4
|
+
return type;
|
|
5
|
+
}
|
|
6
|
+
else if (type instanceof NamedWrappingType) {
|
|
7
|
+
return getTypeAs(type.type, classReference);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
throw new Error(`Type of kind "${type.kind}" is not a ${classReference}!`);
|
|
11
|
+
}
|
|
12
|
+
}
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { isNotDuplicate } from './syntax/helpers.js';
|
|
4
|
+
import { readUserConfig } from './config/getConfig.js';
|
|
5
|
+
import { NitroConfig } from './config/NitroConfig.js';
|
|
6
|
+
export const NITROGEN_VERSION = process.env.npm_package_version ?? '?.?.?';
|
|
7
|
+
export function capitalizeName(name) {
|
|
8
|
+
if (name.length === 0)
|
|
9
|
+
return name;
|
|
10
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
11
|
+
}
|
|
12
|
+
export function createIndentation(spacesCount) {
|
|
13
|
+
return Array.from(Array(spacesCount)).fill(' ').join('');
|
|
14
|
+
}
|
|
15
|
+
export function indent(string, indentation) {
|
|
16
|
+
let spaces;
|
|
17
|
+
if (typeof indentation === 'number') {
|
|
18
|
+
spaces = createIndentation(indentation);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
spaces = indentation;
|
|
22
|
+
}
|
|
23
|
+
return string.replaceAll('\n', `\n${spaces}`);
|
|
24
|
+
}
|
|
25
|
+
export function errorToString(error) {
|
|
26
|
+
if (error == null) {
|
|
27
|
+
return `null`;
|
|
28
|
+
}
|
|
29
|
+
if (typeof error !== 'object') {
|
|
30
|
+
return `${error}`;
|
|
31
|
+
}
|
|
32
|
+
if (error instanceof Error) {
|
|
33
|
+
let message = `${error.name}: ${error.message}`;
|
|
34
|
+
if (error.cause != null) {
|
|
35
|
+
message += ` (cause: ${JSON.stringify(error.cause)})`;
|
|
36
|
+
}
|
|
37
|
+
return message;
|
|
38
|
+
}
|
|
39
|
+
if ('toString' in error) {
|
|
40
|
+
return error.toString();
|
|
41
|
+
}
|
|
42
|
+
return JSON.stringify(error);
|
|
43
|
+
}
|
|
44
|
+
export function escapeComments(string) {
|
|
45
|
+
return string
|
|
46
|
+
.replace(/\/\*/g, '/ *') // Escape start of comment
|
|
47
|
+
.replace(/\*\//g, '* /') // Escape end of comment
|
|
48
|
+
.replace(/\/\//g, '/ /'); // Escape single-line comment
|
|
49
|
+
}
|
|
50
|
+
const HAS_UNIX_PATHS = path.join('a', 'b').includes('/');
|
|
51
|
+
export function toUnixPath(p) {
|
|
52
|
+
if (HAS_UNIX_PATHS)
|
|
53
|
+
return p;
|
|
54
|
+
return p.replaceAll('\\', '/');
|
|
55
|
+
}
|
|
56
|
+
const sep = path.sep;
|
|
57
|
+
export function unsafeFastJoin(...segments) {
|
|
58
|
+
// this function should really not take any unsafe strings like `/` or `\`.
|
|
59
|
+
return segments.join(sep);
|
|
60
|
+
}
|
|
61
|
+
function getFullPath(file) {
|
|
62
|
+
return unsafeFastJoin(file.platform, file.language, ...file.subdirectory, file.name);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Deduplicates all files via their full path.
|
|
66
|
+
* If content differs, you are f*cked.
|
|
67
|
+
*/
|
|
68
|
+
export function deduplicateFiles(files) {
|
|
69
|
+
const map = new Map();
|
|
70
|
+
for (const file of files) {
|
|
71
|
+
const filePath = getFullPath(file);
|
|
72
|
+
if (!map.has(filePath)) {
|
|
73
|
+
map.set(filePath, file);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return [...map.values()];
|
|
77
|
+
}
|
|
78
|
+
export function filterDuplicateHelperBridges(bridge, i, array) {
|
|
79
|
+
const otherIndex = array.findIndex((f2) => bridge.specializationName === f2.specializationName);
|
|
80
|
+
return otherIndex === i;
|
|
81
|
+
}
|
|
82
|
+
export function toLowerCamelCase(string) {
|
|
83
|
+
const parts = string.split('_').filter((part) => part !== '');
|
|
84
|
+
if (parts.length === 0)
|
|
85
|
+
return '';
|
|
86
|
+
const camelCaseString = parts[0].toLowerCase();
|
|
87
|
+
const camelCased = parts
|
|
88
|
+
.slice(1)
|
|
89
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase());
|
|
90
|
+
return camelCaseString + camelCased.join('');
|
|
91
|
+
}
|
|
92
|
+
export function getBaseTypes(type) {
|
|
93
|
+
const baseTypes = type.getBaseTypes();
|
|
94
|
+
const symbol = type.getSymbol();
|
|
95
|
+
if (symbol != null) {
|
|
96
|
+
baseTypes.push(...symbol.getDeclaredType().getBaseTypes());
|
|
97
|
+
}
|
|
98
|
+
const recursive = baseTypes.flatMap((b) => [b, ...getBaseTypes(b)]);
|
|
99
|
+
return recursive.filter(isNotDuplicate);
|
|
100
|
+
}
|
|
101
|
+
export function getHybridObjectNitroModuleConfig(type) {
|
|
102
|
+
const symbol = type.getSymbol() ?? type.getAliasSymbol();
|
|
103
|
+
if (!symbol)
|
|
104
|
+
return undefined;
|
|
105
|
+
const declarations = symbol.getValueDeclaration() || symbol.getDeclarations()[0];
|
|
106
|
+
if (!declarations)
|
|
107
|
+
return undefined;
|
|
108
|
+
const sourceFile = declarations.getSourceFile();
|
|
109
|
+
let filePath = sourceFile.getFilePath();
|
|
110
|
+
while (true) {
|
|
111
|
+
// go up one dir
|
|
112
|
+
const newFilePath = path.resolve(path.join(filePath, '..'));
|
|
113
|
+
if (filePath === newFilePath) {
|
|
114
|
+
// going 'cd ..' in that path didn't change a thing - so we
|
|
115
|
+
// reached the root directory. we didn't find a nitro.json anywhere.
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
filePath = newFilePath;
|
|
119
|
+
const nitroJsonPath = path.join(filePath, 'nitro.json');
|
|
120
|
+
const hasNitroJson = fs.existsSync(nitroJsonPath);
|
|
121
|
+
if (hasNitroJson) {
|
|
122
|
+
const config = readUserConfig(nitroJsonPath);
|
|
123
|
+
return new NitroConfig(config);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { createIndentation, indent } from '../utils.js';
|
|
2
|
+
import { createFileMetadataString, escapeCppName, isFunction, isNotDuplicate, } from '../syntax/helpers.js';
|
|
3
|
+
import { getHybridObjectName } from '../syntax/getHybridObjectName.js';
|
|
4
|
+
import { includeHeader } from '../syntax/c++/includeNitroHeader.js';
|
|
5
|
+
import { createHostComponentJs } from './createHostComponentJs.js';
|
|
6
|
+
import { Property } from '../syntax/Property.js';
|
|
7
|
+
import { FunctionType } from '../syntax/types/FunctionType.js';
|
|
8
|
+
import { VoidType } from '../syntax/types/VoidType.js';
|
|
9
|
+
import { HybridObjectType } from '../syntax/types/HybridObjectType.js';
|
|
10
|
+
import { NamedWrappingType } from '../syntax/types/NamedWrappingType.js';
|
|
11
|
+
import { OptionalType } from '../syntax/types/OptionalType.js';
|
|
12
|
+
export function getViewComponentNames(spec) {
|
|
13
|
+
const name = getHybridObjectName(spec.name);
|
|
14
|
+
return {
|
|
15
|
+
propsClassName: `${name.HybridT}Props`,
|
|
16
|
+
stateClassName: `${name.HybridT}State`,
|
|
17
|
+
nameVariable: `${name.HybridT}ComponentName`,
|
|
18
|
+
shadowNodeClassName: `${name.HybridT}ShadowNode`,
|
|
19
|
+
descriptorClassName: `${name.HybridT}ComponentDescriptor`,
|
|
20
|
+
component: `${name.HybridT}Component`,
|
|
21
|
+
manager: `${name.HybridT}Manager`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function getHybridRefProperty(spec) {
|
|
25
|
+
const hybrid = new HybridObjectType(spec);
|
|
26
|
+
const type = new FunctionType(new VoidType(), [
|
|
27
|
+
new NamedWrappingType('ref', hybrid),
|
|
28
|
+
]);
|
|
29
|
+
return new Property('hybridRef', new OptionalType(type), false);
|
|
30
|
+
}
|
|
31
|
+
export function createViewComponentShadowNodeFiles(spec) {
|
|
32
|
+
if (!spec.isHybridView) {
|
|
33
|
+
throw new Error(`Cannot create View Component ShadowNode code for ${spec.name} - it's not a HybridView!`);
|
|
34
|
+
}
|
|
35
|
+
const { T, HybridT } = getHybridObjectName(spec.name);
|
|
36
|
+
const { propsClassName, stateClassName, nameVariable, shadowNodeClassName, descriptorClassName, component, } = getViewComponentNames(spec);
|
|
37
|
+
const namespace = spec.config.getCxxNamespace('c++', 'views');
|
|
38
|
+
const props = [...spec.properties, getHybridRefProperty(spec)];
|
|
39
|
+
const properties = props.map((p) => `CachedProp<${p.type.getCode('c++')}> ${escapeCppName(p.name)};`);
|
|
40
|
+
const cases = props.map((p) => `case hashString("${p.name}"): return true;`);
|
|
41
|
+
const includes = props
|
|
42
|
+
.flatMap((p) => p.getRequiredImports('c++').map((i) => includeHeader(i, true)))
|
|
43
|
+
.filter(isNotDuplicate);
|
|
44
|
+
// .hpp code
|
|
45
|
+
const shadowIndent = createIndentation(shadowNodeClassName.length);
|
|
46
|
+
const componentHeaderCode = `
|
|
47
|
+
${createFileMetadataString(`${component}.hpp`)}
|
|
48
|
+
|
|
49
|
+
#pragma once
|
|
50
|
+
|
|
51
|
+
#include <optional>
|
|
52
|
+
#include <NitroModules/NitroDefines.hpp>
|
|
53
|
+
#include <NitroModules/NitroHash.hpp>
|
|
54
|
+
#include <NitroModules/CachedProp.hpp>
|
|
55
|
+
#include <react/renderer/core/ConcreteComponentDescriptor.h>
|
|
56
|
+
#include <react/renderer/core/PropsParserContext.h>
|
|
57
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
58
|
+
#include <react/renderer/components/view/ViewProps.h>
|
|
59
|
+
|
|
60
|
+
${includes.join('\n')}
|
|
61
|
+
|
|
62
|
+
namespace ${namespace} {
|
|
63
|
+
|
|
64
|
+
using namespace facebook;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The name of the actual native View.
|
|
68
|
+
*/
|
|
69
|
+
extern const char ${nameVariable}[];
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Props for the "${spec.name}" View.
|
|
73
|
+
*/
|
|
74
|
+
class ${propsClassName} final: public react::ViewProps {
|
|
75
|
+
public:
|
|
76
|
+
${propsClassName}() = default;
|
|
77
|
+
${propsClassName}(const ${propsClassName}&);
|
|
78
|
+
${propsClassName}(const react::PropsParserContext& context,
|
|
79
|
+
${createIndentation(propsClassName.length)} const ${propsClassName}& sourceProps,
|
|
80
|
+
${createIndentation(propsClassName.length)} const react::RawProps& rawProps);
|
|
81
|
+
|
|
82
|
+
public:
|
|
83
|
+
${indent(properties.join('\n'), ' ')}
|
|
84
|
+
|
|
85
|
+
private:
|
|
86
|
+
static bool filterObjectKeys(const std::string& propName);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* State for the "${spec.name}" View.
|
|
91
|
+
*/
|
|
92
|
+
class ${stateClassName} final {
|
|
93
|
+
public:
|
|
94
|
+
${stateClassName}() = default;
|
|
95
|
+
|
|
96
|
+
public:
|
|
97
|
+
void setProps(const ${propsClassName}& props) { _props.emplace(props); }
|
|
98
|
+
const std::optional<${propsClassName}>& getProps() const { return _props; }
|
|
99
|
+
|
|
100
|
+
public:
|
|
101
|
+
#ifdef ANDROID
|
|
102
|
+
${stateClassName}(const ${stateClassName}& /* previousState */, folly::dynamic /* data */) {}
|
|
103
|
+
folly::dynamic getDynamic() const {
|
|
104
|
+
throw std::runtime_error("${stateClassName} does not support folly!");
|
|
105
|
+
}
|
|
106
|
+
react::MapBuffer getMapBuffer() const {
|
|
107
|
+
throw std::runtime_error("${stateClassName} does not support MapBuffer!");
|
|
108
|
+
};
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
private:
|
|
112
|
+
std::optional<${propsClassName}> _props;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The Shadow Node for the "${spec.name}" View.
|
|
117
|
+
*/
|
|
118
|
+
using ${shadowNodeClassName} = react::ConcreteViewShadowNode<${nameVariable} /* "${HybridT}" */,
|
|
119
|
+
${shadowIndent} ${propsClassName} /* custom props */,
|
|
120
|
+
${shadowIndent} react::ViewEventEmitter /* default */,
|
|
121
|
+
${shadowIndent} ${stateClassName} /* custom state */>;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The Component Descriptor for the "${spec.name}" View.
|
|
125
|
+
*/
|
|
126
|
+
class ${descriptorClassName} final: public react::ConcreteComponentDescriptor<${shadowNodeClassName}> {
|
|
127
|
+
public:
|
|
128
|
+
${descriptorClassName}(const react::ComponentDescriptorParameters& parameters);
|
|
129
|
+
|
|
130
|
+
public:
|
|
131
|
+
/**
|
|
132
|
+
* A faster path for cloning props - reuses the caching logic from \`${propsClassName}\`.
|
|
133
|
+
*/
|
|
134
|
+
std::shared_ptr<const react::Props> cloneProps(const react::PropsParserContext& context,
|
|
135
|
+
const std::shared_ptr<const react::Props>& props,
|
|
136
|
+
react::RawProps rawProps) const override;
|
|
137
|
+
#ifdef ANDROID
|
|
138
|
+
void adopt(react::ShadowNode& shadowNode) const override;
|
|
139
|
+
#endif
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/* The actual view for "${spec.name}" needs to be implemented in platform-specific code. */
|
|
143
|
+
|
|
144
|
+
} // namespace ${namespace}
|
|
145
|
+
`.trim();
|
|
146
|
+
// .cpp code
|
|
147
|
+
const propInitializers = [
|
|
148
|
+
'react::ViewProps(context, sourceProps, rawProps, filterObjectKeys)',
|
|
149
|
+
];
|
|
150
|
+
const propCopyInitializers = ['react::ViewProps()'];
|
|
151
|
+
for (const prop of props) {
|
|
152
|
+
const name = escapeCppName(prop.name);
|
|
153
|
+
const type = prop.type.getCode('c++');
|
|
154
|
+
let valueConversion = `value`;
|
|
155
|
+
if (isFunction(prop.type)) {
|
|
156
|
+
// Due to a React limitation, functions cannot be passed to native directly,
|
|
157
|
+
// because RN converts them to booleans (`true`). Nitro knows this and just
|
|
158
|
+
// wraps functions as objects - the original function is stored in `f`.
|
|
159
|
+
valueConversion = `value.asObject(*runtime).getProperty(*runtime, "f")`;
|
|
160
|
+
}
|
|
161
|
+
propInitializers.push(`
|
|
162
|
+
${name}([&]() -> CachedProp<${type}> {
|
|
163
|
+
try {
|
|
164
|
+
const react::RawValue* rawValue = rawProps.at("${prop.name}", nullptr, nullptr);
|
|
165
|
+
if (rawValue == nullptr) return sourceProps.${name};
|
|
166
|
+
const auto& [runtime, value] = (std::pair<jsi::Runtime*, jsi::Value>)*rawValue;
|
|
167
|
+
return CachedProp<${type}>::fromRawValue(*runtime, ${valueConversion}, sourceProps.${name});
|
|
168
|
+
} catch (const std::exception& exc) {
|
|
169
|
+
throw std::runtime_error(std::string("${spec.name}.${prop.name}: ") + exc.what());
|
|
170
|
+
}
|
|
171
|
+
}())`.trim());
|
|
172
|
+
propCopyInitializers.push(`${name}(other.${name})`);
|
|
173
|
+
}
|
|
174
|
+
const ctorIndent = createIndentation(propsClassName.length * 2);
|
|
175
|
+
const descriptorIndent = createIndentation(descriptorClassName.length);
|
|
176
|
+
const componentCode = `
|
|
177
|
+
${createFileMetadataString(`${component}.cpp`)}
|
|
178
|
+
|
|
179
|
+
#include "${component}.hpp"
|
|
180
|
+
|
|
181
|
+
#include <string>
|
|
182
|
+
#include <exception>
|
|
183
|
+
#include <utility>
|
|
184
|
+
#include <NitroModules/NitroDefines.hpp>
|
|
185
|
+
#include <NitroModules/JSIConverter.hpp>
|
|
186
|
+
#include <react/renderer/core/RawValue.h>
|
|
187
|
+
#include <react/renderer/core/ShadowNode.h>
|
|
188
|
+
#include <react/renderer/core/ComponentDescriptor.h>
|
|
189
|
+
#include <react/renderer/components/view/ViewProps.h>
|
|
190
|
+
|
|
191
|
+
namespace ${namespace} {
|
|
192
|
+
|
|
193
|
+
extern const char ${nameVariable}[] = "${T}";
|
|
194
|
+
|
|
195
|
+
${propsClassName}::${propsClassName}(const react::PropsParserContext& context,
|
|
196
|
+
${ctorIndent} const ${propsClassName}& sourceProps,
|
|
197
|
+
${ctorIndent} const react::RawProps& rawProps):
|
|
198
|
+
${indent(propInitializers.join(',\n'), ' ')} { }
|
|
199
|
+
|
|
200
|
+
${propsClassName}::${propsClassName}(const ${propsClassName}& other):
|
|
201
|
+
${indent(propCopyInitializers.join(',\n'), ' ')} { }
|
|
202
|
+
|
|
203
|
+
bool ${propsClassName}::filterObjectKeys(const std::string& propName) {
|
|
204
|
+
switch (hashString(propName)) {
|
|
205
|
+
${indent(cases.join('\n'), ' ')}
|
|
206
|
+
default: return false;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
${descriptorClassName}::${descriptorClassName}(const react::ComponentDescriptorParameters& parameters)
|
|
211
|
+
: ConcreteComponentDescriptor(parameters,
|
|
212
|
+
react::RawPropsParser(/* enableJsiParser */ true)) {}
|
|
213
|
+
|
|
214
|
+
std::shared_ptr<const react::Props> ${descriptorClassName}::cloneProps(const react::PropsParserContext& context,
|
|
215
|
+
${descriptorIndent} const std::shared_ptr<const react::Props>& props,
|
|
216
|
+
${descriptorIndent} react::RawProps rawProps) const {
|
|
217
|
+
// 1. Prepare raw props parser
|
|
218
|
+
rawProps.parse(rawPropsParser_);
|
|
219
|
+
// 2. Copy props with Nitro's cached copy constructor
|
|
220
|
+
return ${shadowNodeClassName}::Props(context, /* & */ rawProps, props);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
#ifdef ANDROID
|
|
224
|
+
void ${descriptorClassName}::adopt(react::ShadowNode& shadowNode) const {
|
|
225
|
+
// This is called immediately after \`ShadowNode\` is created, cloned or in progress.
|
|
226
|
+
// On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++.
|
|
227
|
+
auto& concreteShadowNode = dynamic_cast<${shadowNodeClassName}&>(shadowNode);
|
|
228
|
+
const ${propsClassName}& props = concreteShadowNode.getConcreteProps();
|
|
229
|
+
${stateClassName} state;
|
|
230
|
+
state.setProps(props);
|
|
231
|
+
concreteShadowNode.setStateData(std::move(state));
|
|
232
|
+
}
|
|
233
|
+
#endif
|
|
234
|
+
|
|
235
|
+
} // namespace ${namespace}
|
|
236
|
+
`.trim();
|
|
237
|
+
const files = [
|
|
238
|
+
{
|
|
239
|
+
name: `${component}.hpp`,
|
|
240
|
+
content: componentHeaderCode,
|
|
241
|
+
language: 'c++',
|
|
242
|
+
platform: 'shared',
|
|
243
|
+
subdirectory: ['views'],
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
name: `${component}.cpp`,
|
|
247
|
+
content: componentCode,
|
|
248
|
+
language: 'c++',
|
|
249
|
+
platform: 'shared',
|
|
250
|
+
subdirectory: ['views'],
|
|
251
|
+
},
|
|
252
|
+
];
|
|
253
|
+
const jsFiles = createHostComponentJs(spec);
|
|
254
|
+
files.push(...jsFiles);
|
|
255
|
+
return files;
|
|
256
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getHybridObjectName } from '../syntax/getHybridObjectName.js';
|
|
2
|
+
import { indent } from '../utils.js';
|
|
3
|
+
export function createHostComponentJs(spec) {
|
|
4
|
+
const { T } = getHybridObjectName(spec.name);
|
|
5
|
+
const props = spec.properties.map((p) => `"${p.name}": true`);
|
|
6
|
+
props.push(`"hybridRef": true`);
|
|
7
|
+
const code = `
|
|
8
|
+
{
|
|
9
|
+
"uiViewClassName": "${T}",
|
|
10
|
+
"supportsRawText": false,
|
|
11
|
+
"bubblingEventTypes": {},
|
|
12
|
+
"directEventTypes": {},
|
|
13
|
+
"validAttributes": {
|
|
14
|
+
${indent(props.join(',\n'), ' ')}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
`.trim();
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
content: code,
|
|
21
|
+
language: 'json',
|
|
22
|
+
name: `${T}Config.json`,
|
|
23
|
+
platform: 'shared',
|
|
24
|
+
subdirectory: [],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
}
|