@@ -89,19 +89,24 @@ Maybe<void> Dotenv::SetEnvironment(node::Environment* env) {
8989MaybeLocal<Object> Dotenv::ToObject (Environment* env) const {
9090 EscapableHandleScope scope (env->isolate ());
9191
92- LocalVector<Name> names (env->isolate (), store_ .size ());
93- LocalVector<Value> values (env->isolate (), store_ .size ());
92+ LocalVector<Name> names (env->isolate (), keys_order_ .size ());
93+ LocalVector<Value> values (env->isolate (), keys_order_ .size ());
9494 auto context = env->context ();
9595
9696 Local<Value> tmp;
9797
9898 int n = 0 ;
99- for (const auto & entry : store_) {
100- if (!ToV8Value (context, entry.first ).ToLocal (&tmp)) {
99+ for (const auto & key : keys_order_) {
100+ auto entry = store_.find (key);
101+ if (entry == store_.end ()) {
102+ continue ;
103+ }
104+
105+ if (!ToV8Value (context, entry->first ).ToLocal (&tmp)) {
101106 return MaybeLocal<Object>();
102107 }
103108 names[n] = tmp.As <Name>();
104- if (!ToV8Value (context, entry. second ).ToLocal (&tmp)) {
109+ if (!ToV8Value (context, entry-> second ).ToLocal (&tmp)) {
105110 return MaybeLocal<Object>();
106111 }
107112 values[n++] = tmp;
@@ -138,6 +143,17 @@ std::string_view trim_spaces(std::string_view input) {
138143void Dotenv::ParseContent (const std::string_view input) {
139144 std::string lines (input);
140145
146+ const auto set_entry = [this ](std::string_view entry_key,
147+ std::string entry_value) {
148+ auto [it, inserted] =
149+ store_.insert_or_assign (std::string (entry_key),
150+ std::move (entry_value));
151+
152+ if (inserted) {
153+ keys_order_.push_back (it->first );
154+ }
155+ };
156+
141157 // Handle windows newlines "\r\n": remove "\r" and keep only "\n"
142158 lines.erase (std::remove (lines.begin (), lines.end (), ' \r ' ), lines.end ());
143159
@@ -187,7 +203,7 @@ void Dotenv::ParseContent(const std::string_view input) {
187203
188204 // If the value is not present (e.g. KEY=) set it to an empty string
189205 if (content.empty () || content.front () == ' \n ' ) {
190- store_. insert_or_assign ( std::string ( key) , " " );
206+ set_entry ( key, " " );
191207 continue ;
192208 }
193209
@@ -212,7 +228,7 @@ void Dotenv::ParseContent(const std::string_view input) {
212228 if (content.empty ()) {
213229 // In case the last line is a single key without value
214230 // Example: KEY= (without a newline at the EOF)
215- store_. insert_or_assign ( std::string ( key) , " " );
231+ set_entry ( key, " " );
216232 break ;
217233 }
218234
@@ -232,7 +248,7 @@ void Dotenv::ParseContent(const std::string_view input) {
232248 pos += 1 ;
233249 }
234250
235- store_. insert_or_assign ( std::string (key), multi_line_value);
251+ set_entry (key, std::move ( multi_line_value) );
236252 auto newline = content.find (' \n ' , closing_quote + 1 );
237253 if (newline != std::string_view::npos) {
238254 content.remove_prefix (newline + 1 );
@@ -259,18 +275,18 @@ void Dotenv::ParseContent(const std::string_view input) {
259275 auto newline = content.find (' \n ' );
260276 if (newline != std::string_view::npos) {
261277 value = content.substr (0 , newline);
262- store_. insert_or_assign ( std::string (key), value);
278+ set_entry (key, std::string (value) );
263279 content.remove_prefix (newline + 1 );
264280 } else {
265281 // No newline - take rest of content
266282 value = content;
267- store_. insert_or_assign ( std::string (key), value);
283+ set_entry (key, std::string (value) );
268284 break ;
269285 }
270286 } else {
271287 // Found closing quote - take content between quotes
272288 value = content.substr (1 , closing_quote - 1 );
273- store_. insert_or_assign ( std::string (key), value);
289+ set_entry (key, std::string (value) );
274290 auto newline = content.find (' \n ' , closing_quote + 1 );
275291 if (newline != std::string_view::npos) {
276292 // Use +1 to discard the '\n' itself => next line
@@ -296,7 +312,7 @@ void Dotenv::ParseContent(const std::string_view input) {
296312 value = value.substr (0 , hash_character);
297313 }
298314 value = trim_spaces (value);
299- store_. insert_or_assign ( std::string ( key) , std::string (value));
315+ set_entry ( key, std::string (value));
300316 content.remove_prefix (newline + 1 );
301317 } else {
302318 // Last line without newline
@@ -305,7 +321,7 @@ void Dotenv::ParseContent(const std::string_view input) {
305321 if (hash_char != std::string_view::npos) {
306322 value = content.substr (0 , hash_char);
307323 }
308- store_. insert_or_assign ( std::string (key), trim_spaces (value));
324+ set_entry (key, std::string (trim_spaces (value) ));
309325 content = {};
310326 }
311327 }
0 commit comments