nitrogen 0.31.1 → 0.31.3

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.
Files changed (47) hide show
  1. package/lib/config/nitrogenVersion.d.ts +1 -0
  2. package/lib/config/nitrogenVersion.js +2 -0
  3. package/lib/createPlatformSpec.js +8 -0
  4. package/lib/getPlatformSpecs.d.ts +3 -2
  5. package/lib/getPlatformSpecs.js +12 -10
  6. package/lib/index.js +2 -1
  7. package/lib/nitrogen.js +6 -15
  8. package/lib/syntax/Method.js +4 -0
  9. package/lib/syntax/c++/CppHybridObject.js +4 -2
  10. package/lib/syntax/createType.js +6 -6
  11. package/lib/syntax/isMemberOverridingFromBase.d.ts +11 -0
  12. package/lib/syntax/isMemberOverridingFromBase.js +64 -0
  13. package/lib/syntax/isOverridingFromBase.d.ts +11 -0
  14. package/lib/syntax/isOverridingFromBase.js +64 -0
  15. package/lib/syntax/kotlin/FbjniHybridObject.js +7 -0
  16. package/lib/syntax/kotlin/KotlinHybridObject.js +12 -2
  17. package/lib/syntax/kotlin/KotlinStruct.js +49 -14
  18. package/lib/syntax/kotlin/isBaseObjectMethodName.d.ts +7 -0
  19. package/lib/syntax/kotlin/isBaseObjectMethodName.js +9 -0
  20. package/lib/syntax/swift/SwiftCxxBridgedType.js +5 -29
  21. package/lib/syntax/swift/SwiftCxxTypeHelper.js +2 -28
  22. package/lib/syntax/swift/SwiftHybridObject.js +8 -1
  23. package/lib/syntax/swift/SwiftHybridObjectBridge.js +12 -1
  24. package/lib/syntax/types/AnyHybridObjectType.d.ts +11 -0
  25. package/lib/syntax/types/AnyHybridObjectType.js +40 -0
  26. package/lib/utils.d.ts +0 -1
  27. package/lib/utils.js +0 -1
  28. package/package.json +2 -2
  29. package/src/config/nitrogenVersion.ts +3 -0
  30. package/src/createPlatformSpec.ts +16 -0
  31. package/src/getPlatformSpecs.ts +24 -15
  32. package/src/index.ts +2 -1
  33. package/src/nitrogen.ts +6 -17
  34. package/src/syntax/Method.ts +6 -0
  35. package/src/syntax/c++/CppHybridObject.ts +7 -2
  36. package/src/syntax/createType.ts +5 -5
  37. package/src/syntax/isMemberOverridingFromBase.ts +79 -0
  38. package/src/syntax/kotlin/FbjniHybridObject.ts +7 -0
  39. package/src/syntax/kotlin/KotlinHybridObject.ts +12 -2
  40. package/src/syntax/kotlin/KotlinStruct.ts +61 -15
  41. package/src/syntax/swift/SwiftCxxBridgedType.ts +5 -27
  42. package/src/syntax/swift/SwiftCxxTypeHelper.ts +2 -27
  43. package/src/syntax/swift/SwiftHybridObject.ts +8 -1
  44. package/src/syntax/swift/SwiftHybridObjectBridge.ts +12 -1
  45. package/src/syntax/types/{HybridObjectBaseType.ts → AnyHybridObjectType.ts} +2 -9
  46. package/src/utils.ts +0 -2
  47. package/src/syntax/swift/isPrimitivelyCopyable.ts +0 -20
@@ -7,29 +7,44 @@ import type { SourceFile } from '../SourceFile.js'
7
7
  import type { StructType } from '../types/StructType.js'
8
8
  import { KotlinCxxBridgedType } from './KotlinCxxBridgedType.js'
9
9
 
10
+ interface BridgedProperty {
11
+ name: string
12
+ type: KotlinCxxBridgedType
13
+ }
14
+
10
15
  export function createKotlinStruct(structType: StructType): SourceFile[] {
11
16
  const packageName = NitroConfig.current.getAndroidPackage('java/kotlin')
12
- const parameters = structType.properties
13
- .map((p) =>
14
- `
17
+
18
+ const bridgedProperties = structType.properties.map<BridgedProperty>((p) => ({
19
+ name: p.escapedName,
20
+ type: new KotlinCxxBridgedType(p),
21
+ }))
22
+ // const parameters = structType.properties
23
+ // .map((p) =>
24
+ // `
25
+ // @DoNotStrip
26
+ // @Keep
27
+ // val ${p.escapedName}: ${p.getCode('kotlin')}
28
+ // `.trim()
29
+ // )
30
+ // .join(',\n')
31
+ const properties = bridgedProperties
32
+ .map(({ name, type }) => {
33
+ return `
15
34
  @DoNotStrip
16
35
  @Keep
17
- val ${p.escapedName}: ${p.getCode('kotlin')}
36
+ val ${name}: ${type.getTypeCode('kotlin', false)}
18
37
  `.trim()
19
- )
38
+ })
20
39
  .join(',\n')
21
40
 
22
- const cxxCreateFunctionParameters = structType.properties
23
- .map((p) => {
24
- const bridged = new KotlinCxxBridgedType(p)
25
- return `${p.escapedName}: ${bridged.getTypeCode('kotlin', false)}`
41
+ const cxxCreateFunctionParameters = bridgedProperties
42
+ .map(({ name, type }) => {
43
+ return `${name}: ${type.getTypeCode('kotlin', false)}`
26
44
  })
27
45
  .join(', ')
28
- const cxxCreateFunctionForward = structType.properties
29
- .map((p) => {
30
- const bridged = new KotlinCxxBridgedType(p)
31
- return bridged.parseFromCppToKotlin(p.escapedName, 'kotlin', false)
32
- })
46
+ const cxxCreateFunctionForward = bridgedProperties
47
+ .map((p) => p.name)
33
48
  .join(', ')
34
49
 
35
50
  const extraImports = structType.properties
@@ -37,6 +52,8 @@ val ${p.escapedName}: ${p.getCode('kotlin')}
37
52
  .map((i) => `import ${i.name}`)
38
53
  .filter(isNotDuplicate)
39
54
 
55
+ const secondaryConstructor = createKotlinConstructor(structType)
56
+
40
57
  const code = `
41
58
  ${createFileMetadataString(`${structType.structName}.kt`)}
42
59
 
@@ -52,8 +69,10 @@ ${extraImports.join('\n')}
52
69
  @DoNotStrip
53
70
  @Keep
54
71
  data class ${structType.structName}(
55
- ${indent(parameters, ' ')}
72
+ ${indent(properties, ' ')}
56
73
  ) {
74
+ ${indent(secondaryConstructor, ' ')}
75
+
57
76
  private companion object {
58
77
  /**
59
78
  * Constructor called from C++
@@ -150,6 +169,33 @@ namespace ${cxxNamespace} {
150
169
  return files
151
170
  }
152
171
 
172
+ function createKotlinConstructor(structType: StructType): string {
173
+ const bridgedProperties = structType.properties.map<BridgedProperty>((p) => ({
174
+ name: p.escapedName,
175
+ type: new KotlinCxxBridgedType(p),
176
+ }))
177
+ const needsSpecialHandling = bridgedProperties.some(
178
+ ({ type }) => type.needsSpecialHandling
179
+ )
180
+ if (needsSpecialHandling) {
181
+ const kotlinParams = structType.properties.map(
182
+ (p) => `${p.escapedName}: ${p.getCode('kotlin')}`
183
+ )
184
+ const paramsForward = bridgedProperties.map(({ name, type }) =>
185
+ type.parseFromKotlinToCpp(name, 'kotlin')
186
+ )
187
+ return `
188
+ /**
189
+ * Create a new instance of ${structType.structName} from Kotlin
190
+ */
191
+ constructor(${kotlinParams.join(', ')}):
192
+ this(${paramsForward.join(', ')})
193
+ `.trim()
194
+ } else {
195
+ return `/* primary constructor */`
196
+ }
197
+ }
198
+
153
199
  function createJNIStructInitializer(structType: StructType): string {
154
200
  const lines: string[] = ['static const auto clazz = javaClassStatic();']
155
201
  for (const prop of structType.properties) {
@@ -32,7 +32,6 @@ import { NamedWrappingType } from '../types/NamedWrappingType.js'
32
32
  import { ErrorType } from '../types/ErrorType.js'
33
33
  import { createSwiftFunctionBridge } from './SwiftFunction.js'
34
34
  import type { Language } from '../../getPlatformSpecs.js'
35
- import { isPrimitivelyCopyable } from './isPrimitivelyCopyable.js'
36
35
 
37
36
  // TODO: Remove enum bridge once Swift fixes bidirectional enums crashing the `-Swift.h` header.
38
37
 
@@ -490,20 +489,8 @@ export class SwiftCxxBridgedType implements BridgedType<'swift', 'c++'> {
490
489
  const wrapping = new SwiftCxxBridgedType(array.itemType, true)
491
490
  switch (language) {
492
491
  case 'swift':
493
- if (isPrimitivelyCopyable(array.itemType)) {
494
- // We can primitively copy the data, raw:
495
- const bridge = this.getBridgeOrThrow()
496
- const getDataFunc = `bridge.get_data_${bridge.specializationName}`
497
- return `
498
- { () -> ${array.getCode('swift')} in
499
- let __data = ${getDataFunc}(${cppParameterName})
500
- let __size = ${cppParameterName}.size()
501
- return Array(UnsafeBufferPointer(start: __data, count: __size))
502
- }()`.trim()
503
- } else {
504
- // We have to iterate the element one by one to create a resulting Array (mapped)
505
- return `${cppParameterName}.map({ __item in ${wrapping.parseFromCppToSwift('__item', 'swift')} })`.trim()
506
- }
492
+ // We have to iterate the element one by one to create a resulting Array (mapped)
493
+ return `${cppParameterName}.map({ __item in ${wrapping.parseFromCppToSwift('__item', 'swift')} })`.trim()
507
494
  default:
508
495
  return cppParameterName
509
496
  }
@@ -764,17 +751,9 @@ case ${i}:
764
751
  const wrapping = new SwiftCxxBridgedType(array.itemType, true)
765
752
  switch (language) {
766
753
  case 'swift':
767
- if (isPrimitivelyCopyable(array.itemType)) {
768
- // memory can be copied primitively
769
- const copyFunc = `bridge.${bridge.funcName}`
770
- return `
771
- ${swiftParameterName}.withUnsafeBufferPointer { __pointer -> bridge.${bridge.specializationName} in
772
- return ${copyFunc}(__pointer.baseAddress!, ${swiftParameterName}.count)
773
- }`.trim()
774
- } else {
775
- // array has to be iterated and converted one-by-one
776
- const makeFunc = `bridge.${bridge.funcName}`
777
- return `
754
+ // array has to be iterated and converted one-by-one
755
+ const makeFunc = `bridge.${bridge.funcName}`
756
+ return `
778
757
  { () -> bridge.${bridge.specializationName} in
779
758
  var __vector = ${makeFunc}(${swiftParameterName}.count)
780
759
  for __item in ${swiftParameterName} {
@@ -782,7 +761,6 @@ ${swiftParameterName}.withUnsafeBufferPointer { __pointer -> bridge.${bridge.spe
782
761
  }
783
762
  return __vector
784
763
  }()`.trim()
785
- }
786
764
  default:
787
765
  return swiftParameterName
788
766
  }
@@ -19,7 +19,6 @@ import { VoidType } from '../types/VoidType.js'
19
19
  import { NamedWrappingType } from '../types/NamedWrappingType.js'
20
20
  import { ErrorType } from '../types/ErrorType.js'
21
21
  import { ResultWrappingType } from '../types/ResultWrappingType.js'
22
- import { isPrimitivelyCopyable } from './isPrimitivelyCopyable.js'
23
22
 
24
23
  export interface SwiftCxxHelper {
25
24
  cxxHeader: {
@@ -268,26 +267,8 @@ function createCxxVectorSwiftHelper(type: ArrayType): SwiftCxxHelper {
268
267
  const actualType = type.getCode('c++')
269
268
  const bridgedType = new SwiftCxxBridgedType(type)
270
269
  const name = escapeCppName(actualType)
271
- let code: string
272
- let funcName: string
273
- if (isPrimitivelyCopyable(type.itemType)) {
274
- const itemType = type.itemType.getCode('c++')
275
- funcName = `copy_${name}`
276
- code = `
277
- /**
278
- * Specialized version of \`${escapeComments(actualType)}\`.
279
- */
280
- using ${name} = ${actualType};
281
- inline ${actualType} copy_${name}(const ${itemType}* CONTIGUOUS_MEMORY NON_NULL data, size_t size) noexcept {
282
- return margelo::nitro::FastVectorCopy<${itemType}>(data, size);
283
- }
284
- inline const ${itemType}* CONTIGUOUS_MEMORY NON_NULL get_data_${name}(const ${actualType}& vector) noexcept {
285
- return vector.data();
286
- }
287
- `.trim()
288
- } else {
289
- funcName = `create_${name}`
290
- code = `
270
+ const funcName = `create_${name}`
271
+ const code = `
291
272
  /**
292
273
  * Specialized version of \`${escapeComments(actualType)}\`.
293
274
  */
@@ -297,7 +278,6 @@ inline ${actualType} create_${name}(size_t size) noexcept {
297
278
  vector.reserve(size);
298
279
  return vector;
299
280
  }`.trim()
300
- }
301
281
 
302
282
  return {
303
283
  cxxType: actualType,
@@ -311,11 +291,6 @@ inline ${actualType} create_${name}(size_t size) noexcept {
311
291
  space: 'system',
312
292
  language: 'c++',
313
293
  },
314
- {
315
- name: 'NitroModules/FastVectorCopy.hpp',
316
- space: 'system',
317
- language: 'c++',
318
- },
319
294
  ...bridgedType.getRequiredImports('c++'),
320
295
  ],
321
296
  },
@@ -11,7 +11,7 @@ export function createSwiftHybridObject(spec: HybridObjectSpec): SourceFile[] {
11
11
  const name = getHybridObjectName(spec.name)
12
12
  const protocolName = name.HybridTSpec
13
13
  const properties = spec.properties.map((p) => p.getCode('swift')).join('\n')
14
- const methods = spec.methods.map((p) => p.getCode('swift')).join('\n')
14
+ const methods = spec.methods.map((m) => m.getCode('swift')).join('\n')
15
15
  const extraImports = [
16
16
  ...spec.properties.flatMap((p) => p.getRequiredImports('swift')),
17
17
  ...spec.methods.flatMap((m) => m.getRequiredImports('swift')),
@@ -83,6 +83,13 @@ public protocol ${protocolName}_protocol: ${protocolBaseClasses.join(', ')} {
83
83
  ${indent(methods, ' ')}
84
84
  }
85
85
 
86
+ public extension ${protocolName}_protocol {
87
+ /// Default implementation of \`\`HybridObject.toString\`\`
88
+ func toString() -> String {
89
+ return "[HybridObject ${name.T}]"
90
+ }
91
+ }
92
+
86
93
  /// See \`\`${protocolName}\`\`
87
94
  open class ${protocolName}_base${classBaseClasses.length > 0 ? `: ${classBaseClasses.join(',')}` : ''} {
88
95
  ${indent(baseMembers.join('\n'), ' ')}
@@ -191,7 +191,7 @@ ${hasBase ? `open class ${name.HybridTSpecCxx} : ${baseClasses.join(', ')}` : `o
191
191
  */
192
192
  public func getCxxPart() -> bridge.${bridge.specializationName} {
193
193
  let cachedCxxPart = self.__cxxPart.lock()
194
- if cachedCxxPart.__convertToBool() {
194
+ if Bool(fromCxx: cachedCxxPart) {
195
195
  return cachedCxxPart
196
196
  } else {
197
197
  let newCxxPart = bridge.${bridge.funcName}(self.toUnsafe())
@@ -220,6 +220,14 @@ ${hasBase ? `open class ${name.HybridTSpecCxx} : ${baseClasses.join(', ')}` : `o
220
220
  self.__implementation.dispose()
221
221
  }
222
222
 
223
+ /**
224
+ * Call toString() on the Swift class.
225
+ */
226
+ @inline(__always)
227
+ public ${hasBase ? 'override func' : 'func'} toString() -> String {
228
+ return self.__implementation.toString()
229
+ }
230
+
223
231
  // Properties
224
232
  ${indent(propertiesBridge.join('\n\n'), ' ')}
225
233
 
@@ -390,6 +398,9 @@ namespace ${cxxNamespace} {
390
398
  void dispose() noexcept override {
391
399
  _swiftPart.dispose();
392
400
  }
401
+ std::string toString() override {
402
+ return _swiftPart.toString();
403
+ }
393
404
 
394
405
  public:
395
406
  // Properties
@@ -3,7 +3,7 @@ import { getForwardDeclaration } from '../c++/getForwardDeclaration.js'
3
3
  import type { SourceFile, SourceImport } from '../SourceFile.js'
4
4
  import type { Type, TypeKind } from './Type.js'
5
5
 
6
- export class HybridObjectBaseType implements Type {
6
+ export class AnyHybridObjectType implements Type {
7
7
  constructor() {}
8
8
 
9
9
  get canBePassedByReference(): boolean {
@@ -21,7 +21,7 @@ export class HybridObjectBaseType implements Type {
21
21
  return `std::shared_ptr<HybridObject>`
22
22
  default:
23
23
  throw new Error(
24
- `The base type \`HybridObject\` cannot be used directly in ${language} yet. Use a specific derived class of \`HybridObject\` instead!`
24
+ `\`AnyHybridObject\` cannot be used directly in ${language} yet. Use a specific derived class of \`HybridObject\` instead!`
25
25
  )
26
26
  }
27
27
  }
@@ -50,13 +50,6 @@ export class HybridObjectBaseType implements Type {
50
50
  }
51
51
  )
52
52
  break
53
- case 'kotlin':
54
- imports.push({
55
- name: 'com.margelo.nitro.core.HybridObject',
56
- space: 'system',
57
- language: 'kotlin',
58
- })
59
- break
60
53
  }
61
54
  return imports
62
55
  }
package/src/utils.ts CHANGED
@@ -7,8 +7,6 @@ import { isNotDuplicate } from './syntax/helpers.js'
7
7
  import { readUserConfig } from './config/getConfig.js'
8
8
  import { NitroConfig } from './config/NitroConfig.js'
9
9
 
10
- export const NITROGEN_VERSION = process.env.npm_package_version ?? '?.?.?'
11
-
12
10
  export function capitalizeName(name: string): string {
13
11
  if (name.length === 0) return name
14
12
  return name.charAt(0).toUpperCase() + name.slice(1)
@@ -1,20 +0,0 @@
1
- import type { Type } from '../types/Type.js'
2
-
3
- /**
4
- * Returns `true` if the given {@linkcode type} is a datatype that
5
- * can be copied without running a copy constructor or special logic
6
- * to copy the data over. In other words; it's _primitively copyable_.
7
- */
8
- export function isPrimitivelyCopyable(type: Type): boolean {
9
- switch (type.kind) {
10
- case 'number':
11
- case 'boolean':
12
- case 'bigint':
13
- case 'enum':
14
- case 'null':
15
- case 'void':
16
- return true
17
- default:
18
- return false
19
- }
20
- }