@@ -16,25 +16,26 @@ import _CJavaScriptKit
1616///
1717public struct JSString : LosslessStringConvertible , Equatable {
1818 /// The internal representation of JS compatible string
19- /// The initializers of this type must initialize `jsRef ` or `buffer`.
19+ /// The initializers of this type must initialize `jsObject ` or `buffer`.
2020 /// And the uninitialized one will be lazily initialized
2121 class Guts {
22- var shouldDeallocateRef : Bool = false
23- lazy var jsRef : JavaScriptObjectRef = {
24- self . shouldDeallocateRef = true
25- return buffer . withUTF8 { bufferPtr in
22+ // Owns the JS-side ref via JSObject, whose deinit routes the release to
23+ // the correct thread via swjs_release_remote when destroyed off-owner-thread.
24+ lazy var jsObject : JSObject = {
25+ let ref = buffer . withUTF8 { bufferPtr in
2626 return swjs_decode_string ( bufferPtr . baseAddress ! , Int32 ( bufferPtr . count ) )
2727 }
28+ return JSObject ( id : ref ) // captures ownerTid = current thread here
2829 } ( )
2930
3031 lazy var buffer : String = {
3132 var bytesRef : JavaScriptObjectRef = 0
32- let bytesLength = Int ( swjs_encode_string ( jsRef , & bytesRef ) )
33+ let bytesLength = Int ( swjs_encode_string ( jsObject . id , & bytesRef ) )
3334 // +1 for null terminator
3435 let buffer = UnsafeMutablePointer < UInt8 > . allocate ( capacity : bytesLength + 1 )
3536 defer {
3637 buffer . deallocate ( )
37- swjs_release ( bytesRef )
38+ swjs_release ( bytesRef ) // bytesRef is a same-thread temporary
3839 }
3940 swjs_load_string ( bytesRef , buffer )
4041 buffer [ bytesLength ] = 0
@@ -46,13 +47,7 @@ public struct JSString: LosslessStringConvertible, Equatable {
4647 }
4748
4849 init ( from jsRef : JavaScriptObjectRef ) {
49- self . jsRef = jsRef
50- self . shouldDeallocateRef = true
51- }
52-
53- deinit {
54- guard shouldDeallocateRef else { return }
55- swjs_release ( jsRef )
50+ self . jsObject = JSObject ( id : jsRef )
5651 }
5752 }
5853
@@ -79,7 +74,7 @@ public struct JSString: LosslessStringConvertible, Equatable {
7974 public static func == ( lhs : JSString , rhs : JSString ) -> Bool {
8075 withExtendedLifetime ( lhs . guts ) { lhsGuts in
8176 withExtendedLifetime ( rhs . guts ) { rhsGuts in
82- return swjs_value_equals ( lhsGuts . jsRef , rhsGuts . jsRef )
77+ return swjs_value_equals ( lhsGuts . jsObject . id , rhsGuts . jsObject . id )
8378 }
8479 }
8580 }
@@ -95,6 +90,6 @@ extension JSString: ExpressibleByStringLiteral {
9590extension JSString {
9691
9792 func asInternalJSRef ( ) -> JavaScriptObjectRef {
98- guts . jsRef
93+ guts . jsObject . id
9994 }
10095}
0 commit comments