ladybird/Libraries/LibJS/Runtime/JSONObject.h
Andreas Kling 7025dd1fa7 Libraries: Parse JS strings from UTF-16
Thread UTF-16 string input through JSON, script parsing, Date parsing,
Intl option parsing, Temporal parsing, and the helper library boundaries
that feed those parsers. Preserve ASCII fast paths where the source data
is known to be ASCII.
2026-06-22 19:51:25 +02:00

73 lines
2.8 KiB
C++

/*
* Copyright (c) 2020, Matthew Olsson <mattco@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Utf16StringBuilder.h>
#include <LibJS/Export.h>
#include <LibJS/Runtime/Object.h>
namespace JS {
// A JSON Parse Record is a Record value used to describe the initial state of a
// value parsed from JSON text. https://tc39.es/ecma262/#sec-json-parse-record
struct JSONParseRecord {
// [[Value]]: the value produced by evaluation of [[ParseNode]].
Value value;
// [[Key]]: the property name with which [[Value]] is associated.
Utf16String key;
// NB: In place of the spec's [[ParseNode]] field, we capture the source text
// matched by the parse node up front. It is present only when [[Value]] is
// a primitive, since the reviver context only exposes "source" for those.
Optional<String> source;
// [[Elements]]: if [[Value]] is an Array, the records for its elements; else empty.
Vector<JSONParseRecord> elements;
// [[Entries]]: if [[Value]] is a non-Array Object, the records for its entries; else empty.
Vector<JSONParseRecord> entries;
};
class JS_API JSONObject final : public Object {
JS_OBJECT(JSONObject, Object);
GC_DECLARE_ALLOCATOR(JSONObject);
public:
virtual void initialize(Realm&) override;
virtual ~JSONObject() override = default;
// The base implementation of stringify is exposed because it is used by
// test-js to communicate between the JS tests and the C++ test runner.
static ThrowCompletionOr<Optional<Utf16String>> stringify_impl(VM&, Value value, Value replacer, Value space);
static ThrowCompletionOr<Value> parse_json(VM&, Utf16View text, JSONParseRecord* root_record = nullptr);
private:
explicit JSONObject(Realm&);
struct StringifyState {
GC::Ptr<FunctionObject> replacer_function;
HashTable<GC::Ptr<Object>> seen_objects;
size_t indent_depth { 0 };
Utf16String gap;
Optional<Vector<Utf16String>> property_list;
Utf16StringBuilder builder;
};
// Stringify helpers
static ThrowCompletionOr<bool> serialize_json_property(VM&, StringifyState&, PropertyKey const& key, Object* holder);
static ThrowCompletionOr<void> serialize_json_object(VM&, StringifyState&, Object&);
static ThrowCompletionOr<void> serialize_json_array(VM&, StringifyState&, Object&);
static void quote_json_string(Utf16StringBuilder&, Utf16View const&);
// Parse helpers
static ThrowCompletionOr<Value> internalize_json_property(VM&, Object* holder, PropertyKey const& name, FunctionObject& reviver, JSONParseRecord const* parse_record);
JS_DECLARE_NATIVE_FUNCTION(stringify);
JS_DECLARE_NATIVE_FUNCTION(parse);
JS_DECLARE_NATIVE_FUNCTION(raw_json);
JS_DECLARE_NATIVE_FUNCTION(is_raw_json);
};
}