@@ -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