| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8cc59bf commit d2c6d57
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -294,8 +294,7 @@ | |||
| 294 | 294 | } else if (value->IsString()) { | |
| 295 | 295 | if (type == BinaryTypeEncodingType::IdEncoding || | |
| 296 | 296 | type == BinaryTypeEncodingType::InterfaceDeclarationReference) { | |
| 297 | - std::u16string strValue = tns::ToUtf16String(isolate, value); | ||
| 298 | - id data = [NSString stringWithCharacters:(const unichar*)strValue.data() length:strValue.size()]; | ||
| 297 | + id data = tns::ToNSString(isolate, value); | ||
| 299 | 298 | // this feels wrong but follows the other CFBridgingRetain calls | |
| 300 | 299 | // and also solves a leak | |
| 301 | 300 | auto ref = CFBridgingRetain(data); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -48,8 +48,7 @@ - (id)nextObject { | |||
| 48 | 48 | bool success = array->Get(context, self->index_).ToLocal(&key); | |
| 49 | 49 | tns::Assert(success, isolate); | |
| 50 | 50 | self->index_ += 2; | |
| 51 | - std::u16string keyStr = tns::ToUtf16String(isolate, key); | ||
| 52 | - NSString* result = [NSString stringWithCharacters:(const unichar*)keyStr.data() length:keyStr.length()]; | ||
| 51 | + NSString* result = tns::ToNSString(isolate, key); | ||
| 53 | 52 | return result; | |
| 54 | 53 | } | |
| 55 | 54 | ||
@@ -117,8 +116,7 @@ - (id)nextObject { | |||
| 117 | 116 | bool success = properties->Get(context, (uint)self->index_).ToLocal(&value); | |
| 118 | 117 | tns::Assert(success, isolate); | |
| 119 | 118 | self->index_++; | |
| 120 | - std::u16string result = tns::ToUtf16String(isolate, value); | ||
| 121 | - return [NSString stringWithCharacters:(const unichar*)result.data() length:result.size()]; | ||
| 119 | + return tns::ToNSString(isolate, value); | ||
| 122 | 120 | } | |
| 123 | 121 | ||
| 124 | 122 | return nil; | |
@@ -140,8 +138,7 @@ - (NSArray*)allObjects { | |||
| 140 | 138 | Local<Value> value; | |
| 141 | 139 | bool success = properties->Get(context, i).ToLocal(&value); | |
| 142 | 140 | tns::Assert(success, isolate); | |
| 143 | - std::u16string result = tns::ToUtf16String(isolate, value); | ||
| 144 | - [array addObject:[NSString stringWithCharacters:(const unichar*)result.data() length:result.size()]]; | ||
| 141 | + [array addObject:tns::ToNSString(isolate, value)]; | ||
| 145 | 142 | } | |
| 146 | 143 | ||
| 147 | 144 | return array; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -106,8 +106,8 @@ inline NSString* ToNSString(const std::string& v) { | |||
| 106 | 106 | length:v.length() | |
| 107 | 107 | encoding:NSUTF8StringEncoding] S_AUTORELEASE]; | |
| 108 | 108 | } | |
| 109 | - // this method is a copy of ToString to avoid needless std::string<->NSString | ||
| 110 | - // conversions | ||
| 109 | + // Reads the V8 string's native UTF-16 buffer directly so lone surrogates and | ||
| 110 | + // embedded NUL survive the bridge; a UTF-8 round-trip loses both. | ||
| 111 | 111 | inline NSString* ToNSString(v8::Isolate* isolate, | |
| 112 | 112 | const v8::Local<v8::Value>& value) { | |
| 113 | 113 | if (value.IsEmpty()) { | |
@@ -119,16 +119,15 @@ inline NSString* ToNSString(v8::Isolate* isolate, | |||
| 119 | 119 | return ToNSString(isolate, obj); | |
| 120 | 120 | } | |
| 121 | 121 | ||
| 122 | - v8::String::Utf8Value result(isolate, value); | ||
| 122 | + v8::String::Value result(isolate, value); | ||
| 123 | 123 | ||
| 124 | - const char* val = *result; | ||
| 124 | + const uint16_t* val = *result; | ||
| 125 | 125 | if (val == nullptr) { | |
| 126 | 126 | return @""; | |
| 127 | 127 | } | |
| 128 | 128 | ||
| 129 | - return [[[NSString alloc] initWithBytes:*result | ||
| 130 | - length:result.length() | ||
| 131 | - encoding:NSUTF8StringEncoding] S_AUTORELEASE]; | ||
| 129 | + return [NSString stringWithCharacters:(const unichar*)val | ||
| 130 | + length:result.length()]; | ||
| 132 | 131 | } | |
| 133 | 132 | #endif | |
| 134 | 133 | std::u16string ToUtf16String(v8::Isolate* isolate, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -324,8 +324,7 @@ inline bool isBool() { | |||
| 324 | 324 | } else if (argHelper.isString() && | |
| 325 | 325 | (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference || | |
| 326 | 326 | typeEncoding->type == BinaryTypeEncodingType::IdEncoding)) { | |
| 327 | - std::u16string str = tns::ToUtf16String(isolate, arg); | ||
| 328 | - NSString* result = [NSString stringWithCharacters:(const unichar*)str.data() length:str.size()]; | ||
| 327 | + NSString* result = tns::ToNSString(isolate, arg); | ||
| 329 | 328 | Interop::SetValue(dest, result); | |
| 330 | 329 | } else if (Interop::IsNumbericType(typeEncoding->type) || tns::IsNumber(arg)) { | |
| 331 | 330 | double value = tns::ToNumber(isolate, arg); | |
@@ -687,8 +686,7 @@ inline bool isBool() { | |||
| 687 | 686 | if (arg.IsEmpty() || arg->IsNullOrUndefined()) { | |
| 688 | 687 | return nil; | |
| 689 | 688 | } else if (tns::IsString(arg)) { | |
| 690 | - std::u16string value = tns::ToUtf16String(isolate, arg); | ||
| 691 | - NSString* result = [NSString stringWithCharacters:(const unichar*)value.data() length:value.size()]; | ||
| 689 | + NSString* result = tns::ToNSString(isolate, arg); | ||
| 692 | 690 | return result; | |
| 693 | 691 | } else if (tns::IsNumber(arg)) { | |
| 694 | 692 | double value = tns::ToNumber(isolate, arg); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,6 +45,23 @@ describe(module.id, function () { | |||
| 45 | 45 | expect(codeUnit).toBe(0xDC00); // 0xFFFD (65533) after a lossy UTF-8 round-trip | |
| 46 | 46 | }); | |
| 47 | 47 | ||
| 48 | + it("preserves an embedded NUL when bridging a JS string to NSString", function () { | ||
| 49 | + // U+0000 is a valid JS code unit but terminates a C string, so a bridge | ||
| 50 | + // that went through char* would cut "a\0b" down to "a". Faithful UTF-16 | ||
| 51 | + // bridging keeps all three units. Read the NUL unit straight out of the | ||
| 52 | + // NSString's buffer so the check does not lean on a native-to-JS conversion. | ||
| 53 | + var withNul = "a" + String.fromCharCode(0) + "b"; | ||
| 54 | + var ns = NSString.stringWithString(withNul); | ||
| 55 | + expect(ns.length).toBe(3); | ||
| 56 | + | ||
| 57 | + var buffer = interop.alloc(interop.sizeof(interop.types.uint16)); | ||
| 58 | + ns.getCharactersRange(buffer, NSMakeRange(1, 1)); | ||
| 59 | + var codeUnit = new interop.Reference(interop.types.uint16, buffer).value; | ||
| 60 | + interop.free(buffer); | ||
| 61 | + | ||
| 62 | + expect(codeUnit).toBe(0x0000); // a char* bridge would have stopped before this | ||
| 63 | + }); | ||
| 64 | + | ||
| 48 | 65 | it("NSArray from native (uncached) array access", function () { | |
| 49 | 66 | const res = TNSObjCTypes.new().getNSArrayOfNSURLs(); | |
| 50 | 67 | console.log(res); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments