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,47 @@
|
|
|
1
|
+
import { ArrayType } from './types/ArrayType.js';
|
|
2
|
+
import { FunctionType } from './types/FunctionType.js';
|
|
3
|
+
import { getTypeAs } from './types/getTypeAs.js';
|
|
4
|
+
import { OptionalType } from './types/OptionalType.js';
|
|
5
|
+
import { PromiseType } from './types/PromiseType.js';
|
|
6
|
+
import { RecordType } from './types/RecordType.js';
|
|
7
|
+
import { StructType } from './types/StructType.js';
|
|
8
|
+
import { TupleType } from './types/TupleType.js';
|
|
9
|
+
import { VariantType } from './types/VariantType.js';
|
|
10
|
+
export function getReferencedTypes(type) {
|
|
11
|
+
switch (type.kind) {
|
|
12
|
+
case 'array':
|
|
13
|
+
const array = getTypeAs(type, ArrayType);
|
|
14
|
+
return [type, ...getReferencedTypes(array.itemType)];
|
|
15
|
+
case 'function':
|
|
16
|
+
const func = getTypeAs(type, FunctionType);
|
|
17
|
+
return [
|
|
18
|
+
type,
|
|
19
|
+
...getReferencedTypes(func.returnType),
|
|
20
|
+
...func.parameters.flatMap((t) => getReferencedTypes(t)),
|
|
21
|
+
];
|
|
22
|
+
case 'optional':
|
|
23
|
+
const optional = getTypeAs(type, OptionalType);
|
|
24
|
+
return [type, ...getReferencedTypes(optional.wrappingType)];
|
|
25
|
+
case 'promise':
|
|
26
|
+
const promise = getTypeAs(type, PromiseType);
|
|
27
|
+
return [type, ...getReferencedTypes(promise.resultingType)];
|
|
28
|
+
case 'record':
|
|
29
|
+
const record = getTypeAs(type, RecordType);
|
|
30
|
+
return [
|
|
31
|
+
type,
|
|
32
|
+
...getReferencedTypes(record.keyType),
|
|
33
|
+
...getReferencedTypes(record.valueType),
|
|
34
|
+
];
|
|
35
|
+
case 'struct':
|
|
36
|
+
const struct = getTypeAs(type, StructType);
|
|
37
|
+
return [type, ...struct.properties.flatMap((p) => getReferencedTypes(p))];
|
|
38
|
+
case 'tuple':
|
|
39
|
+
const tuple = getTypeAs(type, TupleType);
|
|
40
|
+
return [type, ...tuple.itemTypes.flatMap((t) => getReferencedTypes(t))];
|
|
41
|
+
case 'variant':
|
|
42
|
+
const variant = getTypeAs(type, VariantType);
|
|
43
|
+
return [type, ...variant.variants.flatMap((t) => getReferencedTypes(t))];
|
|
44
|
+
default:
|
|
45
|
+
return [type];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { getTypeAs } from './types/getTypeAs.js';
|
|
3
|
+
import { OptionalType } from './types/OptionalType.js';
|
|
4
|
+
export function createFileMetadataString(filename, comment = '///') {
|
|
5
|
+
const now = new Date();
|
|
6
|
+
return `
|
|
7
|
+
${comment}
|
|
8
|
+
${comment} ${filename}
|
|
9
|
+
${comment} This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
10
|
+
${comment} https://github.com/mrousavy/nitro
|
|
11
|
+
${comment} Copyright © ${now.getFullYear()} Marc Rousavy @ Margelo
|
|
12
|
+
${comment}
|
|
13
|
+
`.trim();
|
|
14
|
+
}
|
|
15
|
+
export function isFunction(type) {
|
|
16
|
+
switch (type.kind) {
|
|
17
|
+
case 'function':
|
|
18
|
+
return true;
|
|
19
|
+
case 'optional': {
|
|
20
|
+
const optional = getTypeAs(type, OptionalType);
|
|
21
|
+
return isFunction(optional.wrappingType);
|
|
22
|
+
}
|
|
23
|
+
default:
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function toReferenceType(type) {
|
|
28
|
+
return `const ${type}&`;
|
|
29
|
+
}
|
|
30
|
+
export function escapeCppName(string) {
|
|
31
|
+
// Replace non-alphanumeric characters with underscores
|
|
32
|
+
let escapedStr = string.replace(/[^a-zA-Z0-9_]/g, '_');
|
|
33
|
+
// Ensure the first character is a letter or underscore
|
|
34
|
+
if (!/^[a-zA-Z_]/.test(escapedStr)) {
|
|
35
|
+
escapedStr = '_' + escapedStr;
|
|
36
|
+
}
|
|
37
|
+
return escapedStr;
|
|
38
|
+
}
|
|
39
|
+
export function isBooleanPropertyPrefix(name) {
|
|
40
|
+
return name.startsWith('is') || name.startsWith('has');
|
|
41
|
+
}
|
|
42
|
+
export function isNotDuplicate(item, index, array) {
|
|
43
|
+
return array.indexOf(item) === index;
|
|
44
|
+
}
|
|
45
|
+
export function isCppFile(file) {
|
|
46
|
+
return file.name.endsWith('cpp') || file.name.endsWith('c');
|
|
47
|
+
}
|
|
48
|
+
export function getRelativeDirectory(file) {
|
|
49
|
+
return path.join('..', 'nitrogen', 'generated', file.platform, file.language, ...file.subdirectory, file.name);
|
|
50
|
+
}
|
|
51
|
+
export function getRelativeDirectoryGenerated(...subpath) {
|
|
52
|
+
return path.join('..', 'nitrogen', 'generated', ...subpath);
|
|
53
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Type as TSMorphType } from 'ts-morph';
|
|
2
|
+
function isSymbol(type, symbolName) {
|
|
3
|
+
// check the symbol directly
|
|
4
|
+
const symbol = type.getSymbol();
|
|
5
|
+
if (symbol?.getName() === symbolName) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
// loop through the alias symbol alias chain to test each one
|
|
9
|
+
let aliasSymbol = type.getAliasSymbol();
|
|
10
|
+
while (aliasSymbol != null) {
|
|
11
|
+
if (aliasSymbol.getName() === symbolName) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
aliasSymbol = aliasSymbol.getAliasedSymbol();
|
|
15
|
+
}
|
|
16
|
+
// nothing found.
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
export function isPromise(type) {
|
|
20
|
+
return isSymbol(type, 'Promise');
|
|
21
|
+
}
|
|
22
|
+
export function isRecord(type) {
|
|
23
|
+
return isSymbol(type, 'Record');
|
|
24
|
+
}
|
|
25
|
+
export function isArrayBuffer(type) {
|
|
26
|
+
return isSymbol(type, 'ArrayBuffer');
|
|
27
|
+
}
|
|
28
|
+
export function isDate(type) {
|
|
29
|
+
return isSymbol(type, 'Date');
|
|
30
|
+
}
|
|
31
|
+
export function isMap(type) {
|
|
32
|
+
return isSymbol(type, 'AnyMap');
|
|
33
|
+
}
|
|
34
|
+
export function isError(type) {
|
|
35
|
+
return isSymbol(type, 'Error');
|
|
36
|
+
}
|
|
37
|
+
export function isCustomType(type) {
|
|
38
|
+
return (type.getProperty('__customTypeName') != null &&
|
|
39
|
+
type.getProperty('__customTypeConfig') != null);
|
|
40
|
+
}
|
|
41
|
+
export function isSyncFunction(type) {
|
|
42
|
+
if (type.getCallSignatures().length < 1)
|
|
43
|
+
// not a function.
|
|
44
|
+
return false;
|
|
45
|
+
const syncTag = type.getProperty('__syncTag');
|
|
46
|
+
return syncTag != null;
|
|
47
|
+
}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { createIndentation, indent } from '../../utils.js';
|
|
2
|
+
import { getForwardDeclaration } from '../c++/getForwardDeclaration.js';
|
|
3
|
+
import { includeHeader } from '../c++/includeNitroHeader.js';
|
|
4
|
+
import { getAllTypes } from '../getAllTypes.js';
|
|
5
|
+
import { getHybridObjectName } from '../getHybridObjectName.js';
|
|
6
|
+
import { createFileMetadataString, isNotDuplicate } from '../helpers.js';
|
|
7
|
+
import { Method } from '../Method.js';
|
|
8
|
+
import { addJNINativeRegistration } from './JNINativeRegistrations.js';
|
|
9
|
+
import { KotlinCxxBridgedType } from './KotlinCxxBridgedType.js';
|
|
10
|
+
export function createFbjniHybridObject(spec) {
|
|
11
|
+
const name = getHybridObjectName(spec.name);
|
|
12
|
+
// Because we cache JNI methods as `static` inside our method bodies,
|
|
13
|
+
// we need to re-create the method bodies per inherited class.
|
|
14
|
+
// This way `Child`'s statically cached `someMethod()` JNI reference
|
|
15
|
+
// is not the same as `Base`'s statically cached `someMethod()` JNI reference.
|
|
16
|
+
const properties = [
|
|
17
|
+
...spec.properties,
|
|
18
|
+
...spec.baseTypes.flatMap((b) => b.properties),
|
|
19
|
+
];
|
|
20
|
+
const methods = [...spec.methods, ...spec.baseTypes.flatMap((b) => b.methods)];
|
|
21
|
+
const propertiesDecl = properties
|
|
22
|
+
.map((p) => p.getCode('c++', { override: true }))
|
|
23
|
+
.join('\n');
|
|
24
|
+
const methodsDecl = methods
|
|
25
|
+
.map((p) => p.getCode('c++', { override: true }))
|
|
26
|
+
.join('\n');
|
|
27
|
+
const jniClassDescriptor = spec.config.getAndroidPackage('c++/jni', name.HybridTSpec);
|
|
28
|
+
const cxxNamespace = spec.config.getCxxNamespace('c++');
|
|
29
|
+
const spaces = createIndentation(name.JHybridTSpec.length);
|
|
30
|
+
let cppBase = 'JHybridObject';
|
|
31
|
+
if (spec.baseTypes.length > 0) {
|
|
32
|
+
if (spec.baseTypes.length > 1) {
|
|
33
|
+
throw new Error(`${name.T}: Inheriting from multiple HybridObject bases is not yet supported on Kotlin!`);
|
|
34
|
+
}
|
|
35
|
+
const base = spec.baseTypes[0];
|
|
36
|
+
cppBase = getHybridObjectName(base.name).JHybridTSpec;
|
|
37
|
+
if (base.config.isExternalConfig) {
|
|
38
|
+
// It's an external type we inherit from - we have to prefix the namespace
|
|
39
|
+
cppBase = base.config.getCxxNamespace('c++', cppBase);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const cppImports = [];
|
|
43
|
+
for (const base of spec.baseTypes) {
|
|
44
|
+
const { JHybridTSpec } = getHybridObjectName(base.name);
|
|
45
|
+
const headerName = base.config.isExternalConfig
|
|
46
|
+
? `${base.config.getAndroidCxxLibName()}/${JHybridTSpec}.hpp`
|
|
47
|
+
: `${JHybridTSpec}.hpp`;
|
|
48
|
+
cppImports.push({
|
|
49
|
+
language: 'c++',
|
|
50
|
+
name: headerName,
|
|
51
|
+
space: base.config.isExternalConfig ? 'system' : 'user',
|
|
52
|
+
forwardDeclaration: getForwardDeclaration('class', JHybridTSpec, base.config.getCxxNamespace('c++')),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const cppHeaderCode = `
|
|
56
|
+
${createFileMetadataString(`${name.HybridTSpec}.hpp`)}
|
|
57
|
+
|
|
58
|
+
#pragma once
|
|
59
|
+
|
|
60
|
+
#include <NitroModules/JHybridObject.hpp>
|
|
61
|
+
#include <fbjni/fbjni.h>
|
|
62
|
+
#include "${name.HybridTSpec}.hpp"
|
|
63
|
+
|
|
64
|
+
${cppImports
|
|
65
|
+
.map((i) => i.forwardDeclaration)
|
|
66
|
+
.filter((f) => f != null)
|
|
67
|
+
.join('\n')}
|
|
68
|
+
${cppImports.map((i) => includeHeader(i)).join('\n')}
|
|
69
|
+
|
|
70
|
+
namespace ${cxxNamespace} {
|
|
71
|
+
|
|
72
|
+
using namespace facebook;
|
|
73
|
+
|
|
74
|
+
class ${name.JHybridTSpec}: public jni::HybridClass<${name.JHybridTSpec}, ${cppBase}>,
|
|
75
|
+
${spaces} public virtual ${name.HybridTSpec} {
|
|
76
|
+
public:
|
|
77
|
+
static auto constexpr kJavaDescriptor = "L${jniClassDescriptor};";
|
|
78
|
+
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> jThis);
|
|
79
|
+
static void registerNatives();
|
|
80
|
+
|
|
81
|
+
protected:
|
|
82
|
+
// C++ constructor (called from Java via \`initHybrid()\`)
|
|
83
|
+
explicit ${name.JHybridTSpec}(jni::alias_ref<jhybridobject> jThis) :
|
|
84
|
+
HybridObject(${name.HybridTSpec}::TAG),
|
|
85
|
+
HybridBase(jThis),
|
|
86
|
+
_javaPart(jni::make_global(jThis)) {}
|
|
87
|
+
|
|
88
|
+
public:
|
|
89
|
+
~${name.JHybridTSpec}() override {
|
|
90
|
+
// Hermes GC can destroy JS objects on a non-JNI Thread.
|
|
91
|
+
jni::ThreadScope::WithClassLoader([&] { _javaPart.reset(); });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public:
|
|
95
|
+
size_t getExternalMemorySize() noexcept override;
|
|
96
|
+
void dispose() noexcept override;
|
|
97
|
+
|
|
98
|
+
public:
|
|
99
|
+
inline const jni::global_ref<${name.JHybridTSpec}::javaobject>& getJavaPart() const noexcept {
|
|
100
|
+
return _javaPart;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
public:
|
|
104
|
+
// Properties
|
|
105
|
+
${indent(propertiesDecl, ' ')}
|
|
106
|
+
|
|
107
|
+
public:
|
|
108
|
+
// Methods
|
|
109
|
+
${indent(methodsDecl, ' ')}
|
|
110
|
+
|
|
111
|
+
private:
|
|
112
|
+
friend HybridBase;
|
|
113
|
+
using HybridBase::HybridBase;
|
|
114
|
+
jni::global_ref<${name.JHybridTSpec}::javaobject> _javaPart;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
} // namespace ${cxxNamespace}
|
|
118
|
+
`.trim();
|
|
119
|
+
// Make sure we register all native JNI methods on app startup
|
|
120
|
+
addJNINativeRegistration({
|
|
121
|
+
namespace: cxxNamespace,
|
|
122
|
+
className: `${name.JHybridTSpec}`,
|
|
123
|
+
import: {
|
|
124
|
+
name: `${name.JHybridTSpec}.hpp`,
|
|
125
|
+
space: 'user',
|
|
126
|
+
language: 'c++',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
const propertiesImpl = properties
|
|
130
|
+
.map((m) => getFbjniPropertyForwardImplementation(spec, m))
|
|
131
|
+
.join('\n');
|
|
132
|
+
const methodsImpl = methods
|
|
133
|
+
.map((m) => getFbjniMethodForwardImplementation(spec, m, m.name))
|
|
134
|
+
.join('\n');
|
|
135
|
+
const allTypes = getAllTypes(spec);
|
|
136
|
+
allTypes.push(...getAllBaseTypes(spec)); // <-- remember, we copy all base methods & properties over too
|
|
137
|
+
const jniImports = allTypes
|
|
138
|
+
.map((t) => new KotlinCxxBridgedType(t))
|
|
139
|
+
.flatMap((t) => t.getRequiredImports('c++'))
|
|
140
|
+
.filter((i) => i != null);
|
|
141
|
+
const cppIncludes = jniImports
|
|
142
|
+
.map((i) => includeHeader(i))
|
|
143
|
+
.filter(isNotDuplicate);
|
|
144
|
+
const cppForwardDeclarations = jniImports
|
|
145
|
+
.map((i) => i.forwardDeclaration)
|
|
146
|
+
.filter((d) => d != null)
|
|
147
|
+
.filter(isNotDuplicate);
|
|
148
|
+
const cppImplCode = `
|
|
149
|
+
${createFileMetadataString(`${name.JHybridTSpec}.cpp`)}
|
|
150
|
+
|
|
151
|
+
#include "${name.JHybridTSpec}.hpp"
|
|
152
|
+
|
|
153
|
+
${cppForwardDeclarations.join('\n')}
|
|
154
|
+
|
|
155
|
+
${cppIncludes.join('\n')}
|
|
156
|
+
|
|
157
|
+
namespace ${cxxNamespace} {
|
|
158
|
+
|
|
159
|
+
jni::local_ref<${name.JHybridTSpec}::jhybriddata> ${name.JHybridTSpec}::initHybrid(jni::alias_ref<jhybridobject> jThis) {
|
|
160
|
+
return makeCxxInstance(jThis);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
void ${name.JHybridTSpec}::registerNatives() {
|
|
164
|
+
registerHybrid({
|
|
165
|
+
makeNativeMethod("initHybrid", ${name.JHybridTSpec}::initHybrid),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
size_t ${name.JHybridTSpec}::getExternalMemorySize() noexcept {
|
|
170
|
+
static const auto method = javaClassStatic()->getMethod<jlong()>("getMemorySize");
|
|
171
|
+
return method(_javaPart);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
void ${name.JHybridTSpec}::dispose() noexcept {
|
|
175
|
+
static const auto method = javaClassStatic()->getMethod<void()>("dispose");
|
|
176
|
+
method(_javaPart);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Properties
|
|
180
|
+
${indent(propertiesImpl, ' ')}
|
|
181
|
+
|
|
182
|
+
// Methods
|
|
183
|
+
${indent(methodsImpl, ' ')}
|
|
184
|
+
|
|
185
|
+
} // namespace ${cxxNamespace}
|
|
186
|
+
`.trim();
|
|
187
|
+
const files = [];
|
|
188
|
+
files.push({
|
|
189
|
+
content: cppHeaderCode,
|
|
190
|
+
language: 'c++',
|
|
191
|
+
name: `${name.JHybridTSpec}.hpp`,
|
|
192
|
+
subdirectory: [],
|
|
193
|
+
platform: 'android',
|
|
194
|
+
});
|
|
195
|
+
files.push({
|
|
196
|
+
content: cppImplCode,
|
|
197
|
+
language: 'c++',
|
|
198
|
+
name: `${name.JHybridTSpec}.cpp`,
|
|
199
|
+
subdirectory: [],
|
|
200
|
+
platform: 'android',
|
|
201
|
+
});
|
|
202
|
+
return files;
|
|
203
|
+
}
|
|
204
|
+
function getFbjniMethodForwardImplementation(spec, method, jniMethodName) {
|
|
205
|
+
const name = getHybridObjectName(spec.name);
|
|
206
|
+
const returnJNI = new KotlinCxxBridgedType(method.returnType);
|
|
207
|
+
const requiresBridge = returnJNI.needsSpecialHandling ||
|
|
208
|
+
method.parameters.some((p) => {
|
|
209
|
+
const bridged = new KotlinCxxBridgedType(p.type);
|
|
210
|
+
return bridged.needsSpecialHandling;
|
|
211
|
+
});
|
|
212
|
+
const methodName = requiresBridge ? `${jniMethodName}_cxx` : jniMethodName;
|
|
213
|
+
const returnType = returnJNI.asJniReferenceType('local');
|
|
214
|
+
const paramsTypes = method.parameters
|
|
215
|
+
.map((p) => {
|
|
216
|
+
const bridge = new KotlinCxxBridgedType(p.type);
|
|
217
|
+
return `${bridge.asJniReferenceType('alias')} /* ${p.name} */`;
|
|
218
|
+
})
|
|
219
|
+
.join(', ');
|
|
220
|
+
const cxxSignature = `${returnType}(${paramsTypes})`;
|
|
221
|
+
const paramsForward = method.parameters.map((p) => {
|
|
222
|
+
const bridged = new KotlinCxxBridgedType(p.type);
|
|
223
|
+
return bridged.parse(p.name, 'c++', 'kotlin', 'c++');
|
|
224
|
+
});
|
|
225
|
+
paramsForward.unshift('_javaPart'); // <-- first param is always Java `this`
|
|
226
|
+
let body;
|
|
227
|
+
if (returnJNI.hasType) {
|
|
228
|
+
// return something - we need to parse it
|
|
229
|
+
body = `
|
|
230
|
+
static const auto method = javaClassStatic()->getMethod<${cxxSignature}>("${methodName}");
|
|
231
|
+
auto __result = method(${paramsForward.join(', ')});
|
|
232
|
+
return ${returnJNI.parse('__result', 'kotlin', 'c++', 'c++')};
|
|
233
|
+
`;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// void method. no return
|
|
237
|
+
body = `
|
|
238
|
+
static const auto method = javaClassStatic()->getMethod<${cxxSignature}>("${methodName}");
|
|
239
|
+
method(${paramsForward.join(', ')});
|
|
240
|
+
`;
|
|
241
|
+
}
|
|
242
|
+
const code = method.getCode('c++', {
|
|
243
|
+
classDefinitionName: name.JHybridTSpec,
|
|
244
|
+
}, body.trim());
|
|
245
|
+
return code;
|
|
246
|
+
}
|
|
247
|
+
function getFbjniPropertyForwardImplementation(spec, property) {
|
|
248
|
+
const methods = [];
|
|
249
|
+
// getter
|
|
250
|
+
const getter = getFbjniMethodForwardImplementation(spec, property.cppGetter, property.getGetterName('jvm'));
|
|
251
|
+
methods.push(getter);
|
|
252
|
+
if (property.cppSetter != null) {
|
|
253
|
+
// setter
|
|
254
|
+
const setter = getFbjniMethodForwardImplementation(spec, property.cppSetter, property.getSetterName('jvm'));
|
|
255
|
+
methods.push(setter);
|
|
256
|
+
}
|
|
257
|
+
return methods.join('\n');
|
|
258
|
+
}
|
|
259
|
+
function getAllBaseTypes(spec) {
|
|
260
|
+
return spec.baseTypes.flatMap((b) => getAllTypes(b));
|
|
261
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a boxed version of the given primitive type.
|
|
3
|
+
* In JNI/Kotlin, primitive types (like `double` or `boolean`)
|
|
4
|
+
* cannot be nullable, so we need to box them - e.g. as `JDouble` or `JBoolean`.
|
|
5
|
+
*/
|
|
6
|
+
export function getKotlinBoxedPrimitiveType(type) {
|
|
7
|
+
switch (type.kind) {
|
|
8
|
+
case 'number':
|
|
9
|
+
return 'jni::JDouble';
|
|
10
|
+
case 'boolean':
|
|
11
|
+
return 'jni::JBoolean';
|
|
12
|
+
case 'bigint':
|
|
13
|
+
return 'jni::JLong';
|
|
14
|
+
default:
|
|
15
|
+
throw new Error(`Type ${type.kind} is not a primitive!`);
|
|
16
|
+
}
|
|
17
|
+
}
|