|
3 | 3 | #include "blob_serializer_deserializer-inl.h" |
4 | 4 | #include "debug_utils-inl.h" |
5 | 5 | #include "env-inl.h" |
6 | | -#include "json_parser.h" |
7 | 6 | #include "node_contextify.h" |
8 | 7 | #include "node_errors.h" |
9 | 8 | #include "node_external_reference.h" |
10 | 9 | #include "node_internals.h" |
11 | 10 | #include "node_snapshot_builder.h" |
12 | 11 | #include "node_union_bytes.h" |
13 | 12 | #include "node_v8_platform-inl.h" |
| 13 | +#include "simdjson.h" |
14 | 14 | #include "util-inl.h" |
15 | 15 |
|
16 | 16 | // The POSTJECT_SENTINEL_FUSE macro is a string of random characters selected by |
@@ -303,79 +303,131 @@ std::optional<SeaConfig> ParseSingleExecutableConfig( |
303 | 303 | } |
304 | 304 |
|
305 | 305 | SeaConfig result; |
306 | | - JSONParser parser; |
307 | | - if (!parser.Parse(config)) { |
308 | | - FPrintF(stderr, "Cannot parse JSON from %s\n", config_path); |
309 | | - return std::nullopt; |
310 | | - } |
311 | 306 |
|
312 | | - result.main_path = |
313 | | - parser.GetTopLevelStringField("main").value_or(std::string()); |
314 | | - if (result.main_path.empty()) { |
315 | | - FPrintF(stderr, |
316 | | - "\"main\" field of %s is not a non-empty string\n", |
317 | | - config_path); |
318 | | - return std::nullopt; |
319 | | - } |
| 307 | + simdjson::ondemand::parser parser; |
| 308 | + simdjson::ondemand::document document; |
| 309 | + simdjson::ondemand::object main_object; |
| 310 | + simdjson::error_code error = |
| 311 | + parser.iterate(simdjson::pad(config)).get(document); |
320 | 312 |
|
321 | | - result.output_path = |
322 | | - parser.GetTopLevelStringField("output").value_or(std::string()); |
323 | | - if (result.output_path.empty()) { |
| 313 | + if (!error) { |
| 314 | + error = document.get_object().get(main_object); |
| 315 | + } |
| 316 | + if (error) { |
324 | 317 | FPrintF(stderr, |
325 | | - "\"output\" field of %s is not a non-empty string\n", |
326 | | - config_path); |
| 318 | + "Cannot parse JSON from %s: %s\n", |
| 319 | + config_path, |
| 320 | + simdjson::error_message(error)); |
327 | 321 | return std::nullopt; |
328 | 322 | } |
329 | 323 |
|
330 | | - std::optional<bool> disable_experimental_sea_warning = |
331 | | - parser.GetTopLevelBoolField("disableExperimentalSEAWarning"); |
332 | | - if (!disable_experimental_sea_warning.has_value()) { |
333 | | - FPrintF(stderr, |
| 324 | + bool use_snapshot_value = false; |
| 325 | + bool use_code_cache_value = false; |
| 326 | + |
| 327 | + for (auto field : main_object) { |
| 328 | + std::string_view key; |
| 329 | + if (field.unescaped_key().get(key)) { |
| 330 | + FPrintF(stderr, "Cannot read key from %s\n", config_path); |
| 331 | + return std::nullopt; |
| 332 | + } |
| 333 | + if (key == "main") { |
| 334 | + if (field.value().get_string().get(result.main_path) || |
| 335 | + result.main_path.empty()) { |
| 336 | + FPrintF(stderr, |
| 337 | + "\"main\" field of %s is not a non-empty string\n", |
| 338 | + config_path); |
| 339 | + return std::nullopt; |
| 340 | + } |
| 341 | + } else if (key == "output") { |
| 342 | + if (field.value().get_string().get(result.output_path) || |
| 343 | + result.output_path.empty()) { |
| 344 | + FPrintF(stderr, |
| 345 | + "\"output\" field of %s is not a non-empty string\n", |
| 346 | + config_path); |
| 347 | + return std::nullopt; |
| 348 | + } |
| 349 | + } else if (key == "disableExperimentalSEAWarning") { |
| 350 | + bool disable_experimental_sea_warning; |
| 351 | + if (field.value().get_bool().get(disable_experimental_sea_warning)) { |
| 352 | + FPrintF( |
| 353 | + stderr, |
334 | 354 | "\"disableExperimentalSEAWarning\" field of %s is not a Boolean\n", |
335 | 355 | config_path); |
336 | | - return std::nullopt; |
337 | | - } |
338 | | - if (disable_experimental_sea_warning.value()) { |
339 | | - result.flags |= SeaFlags::kDisableExperimentalSeaWarning; |
| 356 | + return std::nullopt; |
| 357 | + } |
| 358 | + if (disable_experimental_sea_warning) { |
| 359 | + result.flags |= SeaFlags::kDisableExperimentalSeaWarning; |
| 360 | + } |
| 361 | + } else if (key == "useSnapshot") { |
| 362 | + if (field.value().get_bool().get(use_snapshot_value)) { |
| 363 | + FPrintF(stderr, |
| 364 | + "\"useSnapshot\" field of %s is not a Boolean\n", |
| 365 | + config_path); |
| 366 | + return std::nullopt; |
| 367 | + } |
| 368 | + if (use_snapshot_value) { |
| 369 | + result.flags |= SeaFlags::kUseSnapshot; |
| 370 | + } |
| 371 | + } else if (key == "useCodeCache") { |
| 372 | + if (field.value().get_bool().get(use_code_cache_value)) { |
| 373 | + FPrintF(stderr, |
| 374 | + "\"useCodeCache\" field of %s is not a Boolean\n", |
| 375 | + config_path); |
| 376 | + return std::nullopt; |
| 377 | + } |
| 378 | + if (use_code_cache_value) { |
| 379 | + result.flags |= SeaFlags::kUseCodeCache; |
| 380 | + } |
| 381 | + } else if (key == "assets") { |
| 382 | + simdjson::ondemand::object assets_object; |
| 383 | + if (field.value().get_object().get(assets_object)) { |
| 384 | + FPrintF(stderr, |
| 385 | + "\"assets\" field of %s is not a map of strings\n", |
| 386 | + config_path); |
| 387 | + return std::nullopt; |
| 388 | + } |
| 389 | + simdjson::ondemand::value asset_value; |
| 390 | + for (auto asset_field : assets_object) { |
| 391 | + std::string_view key_str; |
| 392 | + std::string_view value_str; |
| 393 | + if (asset_field.unescaped_key().get(key_str) || |
| 394 | + asset_field.value().get(asset_value) || |
| 395 | + asset_value.get_string().get(value_str)) { |
| 396 | + FPrintF(stderr, |
| 397 | + "\"assets\" field of %s is not a map of strings\n", |
| 398 | + config_path); |
| 399 | + return std::nullopt; |
| 400 | + } |
| 401 | + |
| 402 | + result.assets.emplace(key_str, value_str); |
| 403 | + } |
| 404 | + |
| 405 | + if (!result.assets.empty()) { |
| 406 | + result.flags |= SeaFlags::kIncludeAssets; |
| 407 | + } |
| 408 | + } |
340 | 409 | } |
341 | 410 |
|
342 | | - std::optional<bool> use_snapshot = parser.GetTopLevelBoolField("useSnapshot"); |
343 | | - if (!use_snapshot.has_value()) { |
344 | | - FPrintF( |
345 | | - stderr, "\"useSnapshot\" field of %s is not a Boolean\n", config_path); |
346 | | - return std::nullopt; |
347 | | - } |
348 | | - if (use_snapshot.value()) { |
349 | | - result.flags |= SeaFlags::kUseSnapshot; |
| 411 | + if (static_cast<bool>(result.flags & SeaFlags::kUseSnapshot) && |
| 412 | + static_cast<bool>(result.flags & SeaFlags::kUseCodeCache)) { |
| 413 | + // TODO(joyeecheung): code cache in snapshot should be configured by |
| 414 | + // separate snapshot configurations. |
| 415 | + FPrintF(stderr, |
| 416 | + "\"useCodeCache\" is redundant when \"useSnapshot\" is true\n"); |
350 | 417 | } |
351 | 418 |
|
352 | | - std::optional<bool> use_code_cache = |
353 | | - parser.GetTopLevelBoolField("useCodeCache"); |
354 | | - if (!use_code_cache.has_value()) { |
355 | | - FPrintF( |
356 | | - stderr, "\"useCodeCache\" field of %s is not a Boolean\n", config_path); |
| 419 | + if (result.main_path.empty()) { |
| 420 | + FPrintF(stderr, |
| 421 | + "\"main\" field of %s is not a non-empty string\n", |
| 422 | + config_path); |
357 | 423 | return std::nullopt; |
358 | 424 | } |
359 | | - if (use_code_cache.value()) { |
360 | | - if (use_snapshot.value()) { |
361 | | - // TODO(joyeecheung): code cache in snapshot should be configured by |
362 | | - // separate snapshot configurations. |
363 | | - FPrintF(stderr, |
364 | | - "\"useCodeCache\" is redundant when \"useSnapshot\" is true\n"); |
365 | | - } else { |
366 | | - result.flags |= SeaFlags::kUseCodeCache; |
367 | | - } |
368 | | - } |
369 | 425 |
|
370 | | - auto assets_opt = parser.GetTopLevelStringDict("assets"); |
371 | | - if (!assets_opt.has_value()) { |
| 426 | + if (result.output_path.empty()) { |
372 | 427 | FPrintF(stderr, |
373 | | - "\"assets\" field of %s is not a map of strings\n", |
| 428 | + "\"output\" field of %s is not a non-empty string\n", |
374 | 429 | config_path); |
375 | 430 | return std::nullopt; |
376 | | - } else if (!assets_opt.value().empty()) { |
377 | | - result.flags |= SeaFlags::kIncludeAssets; |
378 | | - result.assets = std::move(assets_opt.value()); |
379 | 431 | } |
380 | 432 |
|
381 | 433 | return result; |
|
0 commit comments