Skip to content

Commit 29a1a4e

Browse files
committed
add external string creation functions and corresponding nan tests
1 parent 9192e84 commit 29a1a4e

File tree

5 files changed

+176
-0
lines changed

5 files changed

+176
-0
lines changed

packages/emnapi/src/v8/string.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ extern "C" {
66
V8_EXTERN internal::Address _v8_string_new_from_utf8(Isolate* isolate, const char* data, v8::NewStringType type, int length);
77
V8_EXTERN internal::Address _v8_string_new_from_one_byte(Isolate* isolate, const uint8_t* data, v8::NewStringType type, int length);
88
V8_EXTERN internal::Address _v8_string_new_from_two_byte(Isolate* isolate, const uint16_t* data, v8::NewStringType type, int length);
9+
V8_EXTERN internal::Address _v8_string_new_external_one_byte(Isolate* isolate, const char* data, int length);
10+
V8_EXTERN internal::Address _v8_string_new_external_two_byte(Isolate* isolate, const uint16_t* data, int length);
911
V8_EXTERN int _v8_string_utf8_length(const String* self, Isolate* isolate);
1012
V8_EXTERN int _v8_string_length(const String* self);
1113
V8_EXTERN int _v8_string_write_utf8(const String* self, Isolate* isolate, char* buffer, int length, int* nchars_ref, int options);
@@ -34,6 +36,18 @@ MaybeLocal<String> String::NewFromTwoByte(Isolate* isolate, const uint16_t* data
3436
return v8impl::V8LocalValueFromAddress(str).As<String>();
3537
}
3638

39+
MaybeLocal<String> String::NewExternalOneByte(Isolate* isolate, ExternalOneByteStringResource* resource) {
40+
auto str = _v8_string_new_external_one_byte(isolate, resource->data(), static_cast<int>(resource->length()));
41+
if (!str) return MaybeLocal<String>();
42+
return v8impl::V8LocalValueFromAddress(str).As<String>();
43+
}
44+
45+
MaybeLocal<String> String::NewExternalTwoByte(Isolate* isolate, ExternalStringResource* resource) {
46+
auto str = _v8_string_new_external_two_byte(isolate, resource->data(), static_cast<int>(resource->length()));
47+
if (!str) return MaybeLocal<String>();
48+
return v8impl::V8LocalValueFromAddress(str).As<String>();
49+
}
50+
3751
MaybeLocal<RegExp> RegExp::New(Local<Context> context,
3852
Local<String> pattern,
3953
Flags flags) {

packages/emnapi/src/v8/string.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ export function _v8_string_new_from_two_byte (isolate: Ptr, data: Ptr, type: num
5454
return emnapiCtx.napiValueFromJsValue(str)
5555
}
5656

57+
/**
58+
* @__deps $emnapiCtx
59+
* @__deps $emnapiString
60+
* @__sig pppi
61+
*/
62+
export function _v8_string_new_external_one_byte (isolate: Ptr, data: Ptr, length: number): Ptr {
63+
from64('data')
64+
from64('length')
65+
const str = emnapiString.encode(data as number, length === -1, length >>> 0, (c) => String.fromCharCode(c))
66+
return emnapiCtx.napiValueFromJsValue(str)
67+
}
68+
69+
/**
70+
* @__deps $emnapiCtx
71+
* @__deps $emnapiString
72+
* @__sig pppi
73+
*/
74+
export function _v8_string_new_external_two_byte (isolate: Ptr, data: Ptr, length: number): Ptr {
75+
from64('data')
76+
from64('length')
77+
const str = emnapiString.UTF16ToString(data as number, length)
78+
return emnapiCtx.napiValueFromJsValue(str)
79+
}
80+
5781
/**
5882
* @__deps $emnapiCtx
5983
* @__sig pppi

packages/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ if(NOT IS_WASM32)
456456
add_test_v8("nan_json_stringify" "./nan/json-stringify.cpp" ON)
457457
add_test_v8("nan_maybe" "./nan/maybe.cpp" ON)
458458
add_test_v8("nan_methodswithdata" "./nan/methodswithdata.cpp" ON)
459+
add_test_v8("nan_morenews" "./nan/morenews.cpp" ON)
459460
add_test_v8("nan_nannew" "./nan/nannew.cpp" ON)
460461
add_test_v8("nan_news" "./nan/news.cpp" ON)
461462
add_test_v8("nan_persistent" "./nan/persistent.cpp" ON)

packages/test/nan/morenews.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*********************************************************************
2+
* NAN - Native Abstractions for Node.js
3+
*
4+
* Copyright (c) 2018 NAN contributors
5+
*
6+
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
7+
********************************************************************/
8+
9+
#include <nan.h>
10+
11+
using namespace Nan; // NOLINT(build/namespaces)
12+
13+
NAN_METHOD(NewNumber) {
14+
info.GetReturnValue().Set(New(0.5));
15+
}
16+
17+
NAN_METHOD(NewNegativeInteger) {
18+
info.GetReturnValue().Set(New(-1));
19+
}
20+
21+
NAN_METHOD(NewPositiveInteger) {
22+
info.GetReturnValue().Set(New(1));
23+
}
24+
25+
NAN_METHOD(NewUtf8String) {
26+
const char s[] = "strïng";
27+
info.GetReturnValue().Set(New(s).ToLocalChecked());
28+
}
29+
30+
NAN_METHOD(NewLatin1String) {
31+
const uint8_t s[] = "str\xefng";
32+
info.GetReturnValue().Set(NewOneByteString(s).ToLocalChecked());
33+
}
34+
35+
NAN_METHOD(NewUcs2String) {
36+
uint16_t s[] = {'s', 't', 'r', 0xef, 'n', 'g', '\0'};
37+
info.GetReturnValue().Set(New(s).ToLocalChecked());
38+
}
39+
40+
static const uint16_t ws[] = {'s', 't', 'r', 0xef, 'n', 'g', '\0'};
41+
static const char s[] = {'s', 't', 'r', 'i', 'n', 'g', '\0'};
42+
43+
class ExtString : public v8::String::ExternalStringResource {
44+
public:
45+
~ExtString() { }
46+
const uint16_t *data() const { return ws; }
47+
size_t length() const { return sizeof (ws) / sizeof (*ws) - 1; }
48+
};
49+
50+
51+
class ExtAsciiString : public ExternalOneByteStringResource {
52+
public:
53+
~ExtAsciiString() { }
54+
const char *data() const { return s; }
55+
size_t length() const { return sizeof (s) / sizeof (*s) - 1; }
56+
};
57+
58+
NAN_METHOD(NewExternalStringResource) {
59+
v8::Local<v8::String> ext = New(new ExtString()).ToLocalChecked();
60+
info.GetReturnValue().Set(ext);
61+
}
62+
63+
NAN_METHOD(NewExternalAsciiStringResource) {
64+
v8::Local<v8::String> ext = New(new ExtAsciiString()).ToLocalChecked();
65+
info.GetReturnValue().Set(ext);
66+
}
67+
68+
NAN_MODULE_INIT(Init) {
69+
Set(target
70+
, New("newNumber").ToLocalChecked()
71+
, GetFunction(New<v8::FunctionTemplate>(NewNumber)).ToLocalChecked()
72+
);
73+
Set(target
74+
, New("newNegativeInteger").ToLocalChecked()
75+
, GetFunction(New<v8::FunctionTemplate>(NewNegativeInteger))
76+
.ToLocalChecked()
77+
);
78+
Set(target
79+
, New("newPositiveInteger").ToLocalChecked()
80+
, GetFunction(New<v8::FunctionTemplate>(NewPositiveInteger))
81+
.ToLocalChecked()
82+
);
83+
Set(target
84+
, New("newUtf8String").ToLocalChecked()
85+
, GetFunction(New<v8::FunctionTemplate>(NewUtf8String)).ToLocalChecked()
86+
);
87+
Set(target
88+
, New("newLatin1String").ToLocalChecked()
89+
, GetFunction(New<v8::FunctionTemplate>(NewLatin1String)).ToLocalChecked()
90+
);
91+
Set(target
92+
, New("newUcs2String").ToLocalChecked()
93+
, GetFunction(New<v8::FunctionTemplate>(NewUcs2String)).ToLocalChecked()
94+
);
95+
Set(target
96+
, New("newExternalStringResource").ToLocalChecked()
97+
, GetFunction(New<v8::FunctionTemplate>(NewExternalStringResource))
98+
.ToLocalChecked()
99+
);
100+
Set(target
101+
, New("newExternalAsciiStringResource").ToLocalChecked()
102+
, GetFunction(New<v8::FunctionTemplate>(NewExternalAsciiStringResource))
103+
.ToLocalChecked()
104+
);
105+
}
106+
107+
NODE_MODULE(morenews, Init)

packages/test/nan/morenews.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict'
2+
const assert = require('assert')
3+
const tap = require('tap')
4+
const test = tap.test
5+
6+
module.exports = {
7+
target: 'nan_morenews',
8+
test: async function (bindings) {
9+
test('morenews', function (t) {
10+
t.plan(16);
11+
t.type(bindings.newNumber, 'function');
12+
t.type(bindings.newPositiveInteger, 'function');
13+
t.type(bindings.newNegativeInteger, 'function');
14+
t.type(bindings.newUtf8String, 'function');
15+
t.type(bindings.newLatin1String, 'function');
16+
t.type(bindings.newUcs2String, 'function');
17+
t.type(bindings.newExternalStringResource, 'function');
18+
t.type(bindings.newExternalAsciiStringResource, 'function');
19+
20+
t.equal(bindings.newNumber(), 0.5);
21+
t.equal(bindings.newPositiveInteger(), 1);
22+
t.equal(bindings.newNegativeInteger(), -1);
23+
t.equal(bindings.newUtf8String(), 'strïng');
24+
t.equal(bindings.newLatin1String(), 'strïng');
25+
t.equal(bindings.newUcs2String(), 'strïng');
26+
t.equals(bindings.newExternalStringResource(), 'strïng');
27+
t.equals(bindings.newExternalAsciiStringResource(), 'string');
28+
});
29+
}
30+
}

0 commit comments

Comments
 (0)