|
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