Skip to content

Commit 7c3b72a

Browse files
authored
Add Symbol class (#27)
- Add abstract Name class that is the base for String and Symbol classes - Add Symbol class - Add unit tests for both String and Symbol classes
1 parent c7d4df4 commit 7c3b72a

File tree

7 files changed

+187
-3
lines changed

7 files changed

+187
-3
lines changed

napi-inl.h

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,16 @@ inline double Number::DoubleValue() const {
343343
return result;
344344
}
345345

346+
////////////////////////////////////////////////////////////////////////////////
347+
// Name class
348+
////////////////////////////////////////////////////////////////////////////////
349+
350+
inline Name::Name() : Value() {
351+
}
352+
353+
inline Name::Name(napi_env env, napi_value value) : Value(env, value) {
354+
}
355+
346356
////////////////////////////////////////////////////////////////////////////////
347357
// String class
348358
////////////////////////////////////////////////////////////////////////////////
@@ -383,10 +393,10 @@ inline String String::New(napi_env env, const char16_t* val, size_t length) {
383393
return String(env, value);
384394
}
385395

386-
inline String::String() : Value() {
396+
inline String::String() : Name() {
387397
}
388398

389-
inline String::String(napi_env env, napi_value value) : Value(env, value) {
399+
inline String::String(napi_env env, napi_value value) : Name(env, value) {
390400
}
391401

392402
inline String::operator std::string() const {
@@ -421,6 +431,39 @@ inline std::u16string String::Utf16Value() const {
421431
return value;
422432
}
423433

434+
////////////////////////////////////////////////////////////////////////////////
435+
// Symbol class
436+
////////////////////////////////////////////////////////////////////////////////
437+
438+
inline Symbol Symbol::New(napi_env env, const char* description) {
439+
napi_value descriptionValue = description != nullptr ?
440+
String::New(env, description) : static_cast<napi_value>(nullptr);
441+
return Symbol::New(env, descriptionValue);
442+
}
443+
444+
inline Symbol Symbol::New(napi_env env, const std::string& description) {
445+
napi_value descriptionValue = String::New(env, description);
446+
return Symbol::New(env, descriptionValue);
447+
}
448+
449+
inline Symbol Symbol::New(napi_env env, String description) {
450+
napi_value descriptionValue = description;
451+
return Symbol::New(env, descriptionValue);
452+
}
453+
454+
inline Symbol Symbol::New(napi_env env, napi_value description) {
455+
napi_value value;
456+
napi_status status = napi_create_symbol(env, description, &value);
457+
if (status != napi_ok) throw Error::New(env);
458+
return Symbol(env, value);
459+
}
460+
461+
inline Symbol::Symbol() : Name() {
462+
}
463+
464+
inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {
465+
}
466+
424467
////////////////////////////////////////////////////////////////////////////////
425468
// Object class
426469
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,13 @@ namespace Napi {
151151
double DoubleValue() const;
152152
};
153153

154-
class String : public Value {
154+
class Name : public Value {
155+
protected:
156+
Name();
157+
Name(napi_env env, napi_value value);
158+
};
159+
160+
class String : public Name {
155161
public:
156162
static String New(napi_env env, const std::string& value);
157163
static String New(napi_env env, const std::u16string& value);
@@ -169,6 +175,17 @@ namespace Napi {
169175
std::u16string Utf16Value() const;
170176
};
171177

178+
class Symbol : public Name {
179+
public:
180+
static Symbol New(napi_env env, const char* description = nullptr);
181+
static Symbol New(napi_env env, const std::string& description);
182+
static Symbol New(napi_env env, String description);
183+
static Symbol New(napi_env env, napi_value description);
184+
185+
Symbol();
186+
Symbol(napi_env env, napi_value value);
187+
};
188+
172189
class Object : public Value {
173190
public:
174191
static Object New(napi_env env);

test/binding.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ using namespace Napi;
44

55
Object InitError(Env env);
66
Object InitFunction(Env env);
7+
Object InitName(Env env);
78

89
void Init(Env env, Object exports, Object module) {
910
exports.Set("error", InitError(env));
1011
exports.Set("function", InitFunction(env));
12+
exports.Set("name", InitName(env));
1113
}
1214

1315
NODE_API_MODULE(addon, Init)

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'binding.cc',
77
'error.cc',
88
'function.cc',
9+
'name.cc',
910
],
1011
'include_dirs': ["<!(node -p \"require('../').include\")"],
1112
'dependencies': ["<!(node -p \"require('../').gyp\")"],

test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
let testModules = [
44
'error',
55
'function',
6+
'name',
67
];
78

89
testModules.forEach(name => {

test/name.cc

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "napi.h"
2+
3+
using namespace Napi;
4+
5+
const char* testValueUtf8 = "123456789";
6+
const char16_t* testValueUtf16 = u"123456789";
7+
8+
Value CreateString(const CallbackInfo& info) {
9+
String encoding = info[0].As<String>();
10+
Number length = info[1].As<Number>();
11+
12+
if (encoding.Utf8Value() == "utf8") {
13+
if (length.IsUndefined()) {
14+
return String::New(info.Env(), testValueUtf8);
15+
} else {
16+
return String::New(info.Env(), testValueUtf8, length.Uint32Value());
17+
}
18+
} else if (encoding.Utf8Value() == "utf16") {
19+
if (length.IsUndefined()) {
20+
return String::New(info.Env(), testValueUtf16);
21+
} else {
22+
return String::New(info.Env(), testValueUtf16, length.Uint32Value());
23+
}
24+
} else {
25+
throw Error::New(info.Env(), "Invalid encoding.");
26+
}
27+
}
28+
29+
Value CheckString(const CallbackInfo& info) {
30+
String value = info[0].As<String>();
31+
String encoding = info[1].As<String>();
32+
Number length = info[2].As<Number>();
33+
34+
if (encoding.Utf8Value() == "utf8") {
35+
std::string testValue = testValueUtf8;
36+
if (!length.IsUndefined()) {
37+
testValue = testValue.substr(0, length.Uint32Value());
38+
}
39+
40+
std::string stringValue = value;
41+
return Boolean::New(info.Env(), stringValue == testValue);
42+
} else if (encoding.Utf8Value() == "utf16") {
43+
std::u16string testValue = testValueUtf16;
44+
if (!length.IsUndefined()) {
45+
testValue = testValue.substr(0, length.Uint32Value());
46+
}
47+
48+
std::u16string stringValue = value;
49+
return Boolean::New(info.Env(), stringValue == testValue);
50+
} else {
51+
throw Error::New(info.Env(), "Invalid encoding.");
52+
}
53+
}
54+
55+
Value CreateSymbol(const CallbackInfo& info) {
56+
String description = info[0].As<String>();
57+
58+
if (!description.IsUndefined()) {
59+
return Symbol::New(info.Env(), description);
60+
} else {
61+
return Symbol::New(info.Env());
62+
}
63+
}
64+
65+
Value CheckSymbol(const CallbackInfo& info) {
66+
return Boolean::New(info.Env(), info[0].Type() == napi_symbol);
67+
}
68+
69+
Object InitName(Env env) {
70+
Object exports = Object::New(env);
71+
72+
exports["createString"] = Function::New(env, CreateString);
73+
exports["checkString"] = Function::New(env, CheckString);
74+
exports["createSymbol"] = Function::New(env, CreateSymbol);
75+
exports["checkSymbol"] = Function::New(env, CheckSymbol);
76+
77+
return exports;
78+
}

test/name.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
const buildType = process.config.target_defaults.default_configuration;
3+
const binding = require(`./build/${buildType}/binding.node`);
4+
const assert = require('assert');
5+
6+
const expected = '123456789';
7+
8+
assert.ok(binding.name.checkString(expected, 'utf8'));
9+
assert.ok(binding.name.checkString(expected, 'utf16'));
10+
assert.ok(binding.name.checkString(expected.substr(0, 3), 'utf8', 3));
11+
assert.ok(binding.name.checkString(expected.substr(0, 3), 'utf16', 3));
12+
13+
const str1 = binding.name.createString('utf8');
14+
assert.strictEqual(str1, expected);
15+
assert.ok(binding.name.checkString(str1, 'utf8'));
16+
assert.ok(binding.name.checkString(str1, 'utf16'));
17+
18+
const substr1 = binding.name.createString('utf8', 3);
19+
assert.strictEqual(substr1, expected.substr(0, 3));
20+
assert.ok(binding.name.checkString(substr1, 'utf8', 3));
21+
assert.ok(binding.name.checkString(substr1, 'utf16', 3));
22+
23+
const str2 = binding.name.createString('utf16');
24+
assert.strictEqual(str1, expected);
25+
assert.ok(binding.name.checkString(str2, 'utf8'));
26+
assert.ok(binding.name.checkString(str2, 'utf16'));
27+
28+
const substr2 = binding.name.createString('utf16', 3);
29+
assert.strictEqual(substr1, expected.substr(0, 3));
30+
assert.ok(binding.name.checkString(substr2, 'utf8', 3));
31+
assert.ok(binding.name.checkString(substr2, 'utf16', 3));
32+
33+
assert.ok(binding.name.checkSymbol(Symbol()));
34+
assert.ok(binding.name.checkSymbol(Symbol('test')));
35+
36+
const sym1 = binding.name.createSymbol();
37+
assert.strictEqual(typeof sym1, 'symbol');
38+
assert.ok(binding.name.checkSymbol(sym1));
39+
40+
const sym2 = binding.name.createSymbol('test');
41+
assert.strictEqual(typeof sym2, 'symbol');
42+
assert.ok(binding.name.checkSymbol(sym1));

0 commit comments

Comments
 (0)