Permalink
Browse files

src: make process.env work with symbols in/delete

The getter for process.env already allows symbols to be used, and `in`
operator as a read-only operator can do the same.

`delete a[b]` operator in ES always returns `true` without doing
anything when `b in a === false`. Allow symbols in the deleter
accordingly.

PR-URL: #11709
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information...
TimothyGu committed Mar 6, 2017
1 parent 7a4adb5 commit e2f151f5b2e76b944bb17f1b324805da6cd2424e
Showing with 28 additions and 23 deletions.
  1. +23 −19 src/node.cc
  2. +5 −4 test/parallel/test-process-env-symbols.js
View
@@ -2787,39 +2787,43 @@ static void EnvSetter(Local<Name> property,
static void EnvQuery(Local<Name> property,
const PropertyCallbackInfo<Integer>& info) {
int32_t rc = -1; // Not found unless proven otherwise.
+ if (property->IsString()) {
#ifdef __POSIX__
- node::Utf8Value key(info.GetIsolate(), property);
- if (getenv(*key))
- rc = 0;
+ node::Utf8Value key(info.GetIsolate(), property);
+ if (getenv(*key))
+ rc = 0;
#else // _WIN32
- node::TwoByteValue key(info.GetIsolate(), property);
- WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
- if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
- GetLastError() == ERROR_SUCCESS) {
- rc = 0;
- if (key_ptr[0] == L'=') {
- // Environment variables that start with '=' are hidden and read-only.
- rc = static_cast<int32_t>(v8::ReadOnly) |
- static_cast<int32_t>(v8::DontDelete) |
- static_cast<int32_t>(v8::DontEnum);
+ node::TwoByteValue key(info.GetIsolate(), property);
+ WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
+ if (GetEnvironmentVariableW(key_ptr, nullptr, 0) > 0 ||
+ GetLastError() == ERROR_SUCCESS) {
+ rc = 0;
+ if (key_ptr[0] == L'=') {
+ // Environment variables that start with '=' are hidden and read-only.
+ rc = static_cast<int32_t>(v8::ReadOnly) |
+ static_cast<int32_t>(v8::DontDelete) |
+ static_cast<int32_t>(v8::DontEnum);
+ }
}
- }
#endif
+ }
if (rc != -1)
info.GetReturnValue().Set(rc);
}
static void EnvDeleter(Local<Name> property,
const PropertyCallbackInfo<Boolean>& info) {
+ if (property->IsString()) {
#ifdef __POSIX__
- node::Utf8Value key(info.GetIsolate(), property);
- unsetenv(*key);
+ node::Utf8Value key(info.GetIsolate(), property);
+ unsetenv(*key);
#else
- node::TwoByteValue key(info.GetIsolate(), property);
- WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
- SetEnvironmentVariableW(key_ptr, nullptr);
+ node::TwoByteValue key(info.GetIsolate(), property);
+ WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
+ SetEnvironmentVariableW(key_ptr, nullptr);
#endif
+ }
// process.env never has non-configurable properties, so always
// return true like the tc39 delete operator.
@@ -18,10 +18,11 @@ assert.throws(() => {
process.env.foo = symbol;
}, errRegExp);
-// Verify that using a symbol with the in operator throws.
-assert.throws(() => {
- symbol in process.env;
-}, errRegExp);
+// Verify that using a symbol with the in operator returns false.
+assert.strictEqual(symbol in process.env, false);
+
+// Verify that deleting a symbol key returns true.
+assert.strictEqual(delete process.env[symbol], true);
// Checks that well-known symbols like `Symbol.toStringTag` won’t throw.
assert.doesNotThrow(() => Object.prototype.toString.call(process.env));

0 comments on commit e2f151f

Please sign in to comment.