mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
src: improve performance of dotenv ToObject
Improves the performance of the dotenv parser ToObject method. Also, switch to a null prototype object to avoid potential prototype pollution issues. PR-URL: https://github.com/nodejs/node/pull/60038 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
parent
6f941fcfba
commit
10df38a38b
|
|
@ -9,8 +9,10 @@ namespace node {
|
||||||
using v8::EscapableHandleScope;
|
using v8::EscapableHandleScope;
|
||||||
using v8::JustVoid;
|
using v8::JustVoid;
|
||||||
using v8::Local;
|
using v8::Local;
|
||||||
|
using v8::LocalVector;
|
||||||
using v8::Maybe;
|
using v8::Maybe;
|
||||||
using v8::MaybeLocal;
|
using v8::MaybeLocal;
|
||||||
|
using v8::Name;
|
||||||
using v8::Nothing;
|
using v8::Nothing;
|
||||||
using v8::Object;
|
using v8::Object;
|
||||||
using v8::String;
|
using v8::String;
|
||||||
|
|
@ -86,20 +88,29 @@ Maybe<void> Dotenv::SetEnvironment(node::Environment* env) {
|
||||||
|
|
||||||
MaybeLocal<Object> Dotenv::ToObject(Environment* env) const {
|
MaybeLocal<Object> Dotenv::ToObject(Environment* env) const {
|
||||||
EscapableHandleScope scope(env->isolate());
|
EscapableHandleScope scope(env->isolate());
|
||||||
Local<Object> result = Object::New(env->isolate());
|
|
||||||
|
|
||||||
Local<Value> name;
|
LocalVector<Name> names(env->isolate(), store_.size());
|
||||||
Local<Value> val;
|
LocalVector<Value> values(env->isolate(), store_.size());
|
||||||
auto context = env->context();
|
auto context = env->context();
|
||||||
|
|
||||||
|
Local<Value> tmp;
|
||||||
|
|
||||||
|
int n = 0;
|
||||||
for (const auto& entry : store_) {
|
for (const auto& entry : store_) {
|
||||||
if (!ToV8Value(context, entry.first).ToLocal(&name) ||
|
if (!ToV8Value(context, entry.first).ToLocal(&tmp)) {
|
||||||
!ToV8Value(context, entry.second).ToLocal(&val) ||
|
|
||||||
result->Set(context, name, val).IsNothing()) {
|
|
||||||
return MaybeLocal<Object>();
|
return MaybeLocal<Object>();
|
||||||
}
|
}
|
||||||
|
names[n] = tmp.As<Name>();
|
||||||
|
if (!ToV8Value(context, entry.second).ToLocal(&tmp)) {
|
||||||
|
return MaybeLocal<Object>();
|
||||||
|
}
|
||||||
|
values[n++] = tmp;
|
||||||
}
|
}
|
||||||
|
Local<Object> result = Object::New(env->isolate(),
|
||||||
|
Null(env->isolate()),
|
||||||
|
names.data(),
|
||||||
|
values.data(),
|
||||||
|
values.size());
|
||||||
return scope.Escape(result);
|
return scope.Escape(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,7 @@ describe('.env supports edge cases', () => {
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
|
__proto__: null,
|
||||||
baz: 'whatever',
|
baz: 'whatever',
|
||||||
VALID_AFTER_INVALID: 'test',
|
VALID_AFTER_INVALID: 'test',
|
||||||
ANOTHER_VALID: 'value',
|
ANOTHER_VALID: 'value',
|
||||||
|
|
@ -236,6 +237,7 @@ describe('.env supports edge cases', () => {
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
|
__proto__: null,
|
||||||
KEY_WITH_SPACES_BEFORE: 'value_with_spaces_before_and_after',
|
KEY_WITH_SPACES_BEFORE: 'value_with_spaces_before_and_after',
|
||||||
KEY_WITH_TABS_BEFORE: 'value_with_tabs_before_and_after',
|
KEY_WITH_TABS_BEFORE: 'value_with_tabs_before_and_after',
|
||||||
KEY_WITH_SPACES_AND_TABS: 'value_with_spaces_and_tabs',
|
KEY_WITH_SPACES_AND_TABS: 'value_with_spaces_and_tabs',
|
||||||
|
|
@ -255,6 +257,7 @@ describe('.env supports edge cases', () => {
|
||||||
].join('\n'));
|
].join('\n'));
|
||||||
|
|
||||||
assert.deepStrictEqual(result, {
|
assert.deepStrictEqual(result, {
|
||||||
|
__proto__: null,
|
||||||
KEY_WITH_COMMENT_IN_VALUE: 'value # this is a comment',
|
KEY_WITH_COMMENT_IN_VALUE: 'value # this is a comment',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,8 @@ const fs = require('node:fs');
|
||||||
const validEnvFilePath = fixtures.path('dotenv/valid.env');
|
const validEnvFilePath = fixtures.path('dotenv/valid.env');
|
||||||
const validContent = fs.readFileSync(validEnvFilePath, 'utf8');
|
const validContent = fs.readFileSync(validEnvFilePath, 'utf8');
|
||||||
|
|
||||||
assert.deepStrictEqual(util.parseEnv(validContent), {
|
const checkObj = {
|
||||||
|
__proto__: null,
|
||||||
A: 'B=C',
|
A: 'B=C',
|
||||||
B: 'C=D',
|
B: 'C=D',
|
||||||
AFTER_LINE: 'after_line',
|
AFTER_LINE: 'after_line',
|
||||||
|
|
@ -56,11 +57,14 @@ const fs = require('node:fs');
|
||||||
SPACED_KEY: 'parsed',
|
SPACED_KEY: 'parsed',
|
||||||
SPACE_BEFORE_DOUBLE_QUOTES: 'space before double quotes',
|
SPACE_BEFORE_DOUBLE_QUOTES: 'space before double quotes',
|
||||||
TRIM_SPACE_FROM_UNQUOTED: 'some spaced out string',
|
TRIM_SPACE_FROM_UNQUOTED: 'some spaced out string',
|
||||||
});
|
};
|
||||||
|
|
||||||
|
assert.deepStrictEqual(util.parseEnv(validContent), checkObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.deepStrictEqual(util.parseEnv(''), {});
|
assert.deepStrictEqual(util.parseEnv(''), { __proto__: null });
|
||||||
assert.deepStrictEqual(util.parseEnv('FOO=bar\nFOO=baz\n'), { FOO: 'baz' });
|
assert.deepStrictEqual(util.parseEnv('FOO=bar\nFOO=baz\n'),
|
||||||
|
{ __proto__: null, FOO: 'baz' });
|
||||||
|
|
||||||
// Test for invalid input.
|
// Test for invalid input.
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user