Skip to content

Commit 7b214cf

Browse files
authored
Introduce bundling modes to opt-out from meta schema bundling (#853)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent bbce14f commit 7b214cf

20 files changed

Lines changed: 1129 additions & 365 deletions

File tree

benchmark/bundle.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ static void Schema_Bundle_Meta_2020_12(benchmark::State &state) {
1010
"https://json-schema.org/draft/2020-12/schema")
1111
.value()};
1212
state.ResumeTiming();
13-
sourcemeta::blaze::bundle(schema, sourcemeta::blaze::schema_walker,
14-
sourcemeta::blaze::schema_resolver);
13+
sourcemeta::blaze::bundle(
14+
schema, sourcemeta::blaze::schema_walker,
15+
sourcemeta::blaze::schema_resolver,
16+
sourcemeta::blaze::BundleMode::NonOfficialMetaschemas);
1517
benchmark::DoNotOptimize(schema);
1618
}
1719
}

src/bundle/bundle.cc

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,17 @@
1616

1717
namespace {
1818

19-
auto is_official_metaschema_reference(
19+
auto is_skippable_metaschema_reference(
20+
const sourcemeta::blaze::BundleMode mode,
2021
const sourcemeta::core::WeakPointer &pointer,
2122
const std::string &destination) -> bool {
2223
assert(!pointer.empty());
2324
assert(pointer.back().is_property());
24-
return pointer.back().to_property() == "$schema" &&
25+
if (pointer.back().to_property() != "$schema") {
26+
return false;
27+
}
28+
29+
return mode == sourcemeta::blaze::BundleMode::References ||
2530
sourcemeta::blaze::is_official_schema(destination);
2631
}
2732

@@ -47,7 +52,9 @@ auto dependencies_internal(
4752
const auto &reference) {
4853
// We don't want to report official schemas, as we can expect
4954
// virtually all implementations to understand them out of the box
50-
if (is_official_metaschema_reference(pointer, reference.destination)) {
55+
if (is_skippable_metaschema_reference(
56+
sourcemeta::blaze::BundleMode::NonOfficialMetaschemas, pointer,
57+
reference.destination)) {
5158
return;
5259
}
5360

@@ -236,6 +243,7 @@ auto bundle_schema(sourcemeta::core::JSON &root,
236243
sourcemeta::core::JSON &subschema,
237244
const sourcemeta::blaze::SchemaWalker &walker,
238245
const sourcemeta::blaze::SchemaResolver &resolver,
246+
const sourcemeta::blaze::BundleMode mode,
239247
std::string_view default_dialect,
240248
std::string_view default_id,
241249
const sourcemeta::blaze::SchemaFrame::Paths &paths,
@@ -265,8 +273,10 @@ auto bundle_schema(sourcemeta::core::JSON &root,
265273
frame.for_each_unresolved_reference([&](const auto &pointer,
266274
const auto &reference) {
267275
// We don't want to bundle official schemas, as we can expect
268-
// virtually all implementations to understand them out of the box
269-
if (is_official_metaschema_reference(pointer, reference.destination)) {
276+
// virtually all implementations to understand them out of the box.
277+
// Depending on the bundling strategy, we may skip meta-schemas entirely
278+
if (is_skippable_metaschema_reference(mode, pointer,
279+
reference.destination)) {
270280
return;
271281
}
272282

@@ -378,8 +388,8 @@ auto bundle_schema(sourcemeta::core::JSON &root,
378388
}
379389

380390
for (auto &[remote, effective_id, remote_dialect] : deferred) {
381-
bundle_schema(root, container, remote, walker, resolver, default_dialect,
382-
effective_id, paths, bundled, depth + 1);
391+
bundle_schema(root, container, remote, walker, resolver, mode,
392+
default_dialect, effective_id, paths, bundled, depth + 1);
383393
elevate_embedded_resources(remote, root, container, remote_dialect,
384394
resolver, default_dialect, bundled);
385395
embed_schema(root, container, effective_id, std::move(remote));
@@ -403,8 +413,8 @@ auto dependencies(const sourcemeta::core::JSON &schema,
403413
// TODO: Refactor this function to internally rely on the `.dependencies()`
404414
// function
405415
auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
406-
const SchemaResolver &resolver, std::string_view default_dialect,
407-
std::string_view default_id,
416+
const SchemaResolver &resolver, const BundleMode mode,
417+
std::string_view default_dialect, std::string_view default_id,
408418
const std::optional<sourcemeta::core::Pointer> &default_container,
409419
const SchemaFrame::Paths &paths) -> void {
410420
// Pre-scan the schema to find any already-embedded schemas and mark them
@@ -424,7 +434,7 @@ auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
424434
// This is undefined behavior
425435
assert(!default_container.value().empty());
426436
bundle_schema(schema, default_container.value(), schema, walker, resolver,
427-
default_dialect, default_id, paths, bundled);
437+
mode, default_dialect, default_id, paths, bundled);
428438
return;
429439
}
430440

@@ -477,18 +487,18 @@ auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
477487
}
478488

479489
bundle_schema(schema, {sourcemeta::core::JSON::String{container_keyword}},
480-
schema, walker, resolver, default_dialect, default_id, paths,
481-
bundled);
490+
schema, walker, resolver, mode, default_dialect, default_id,
491+
paths, bundled);
482492
}
483493

484494
auto bundle(const sourcemeta::core::JSON &schema, const SchemaWalker &walker,
485-
const SchemaResolver &resolver, std::string_view default_dialect,
486-
std::string_view default_id,
495+
const SchemaResolver &resolver, const BundleMode mode,
496+
std::string_view default_dialect, std::string_view default_id,
487497
const std::optional<sourcemeta::core::Pointer> &default_container,
488498
const SchemaFrame::Paths &paths) -> sourcemeta::core::JSON {
489499
sourcemeta::core::JSON copy = schema;
490-
bundle(copy, walker, resolver, default_dialect, default_id, default_container,
491-
paths);
500+
bundle(copy, walker, resolver, mode, default_dialect, default_id,
501+
default_container, paths);
492502
return copy;
493503
}
494504

src/bundle/include/sourcemeta/blaze/bundle.h

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <sourcemeta/blaze/foundation.h>
2121
#include <sourcemeta/blaze/frame.h>
2222

23+
#include <cstdint> // std::uint8_t
2324
#include <functional> // std::function
2425
#include <optional> // std::optional, std::nullopt
2526
#include <string_view> // std::string_view
@@ -36,6 +37,18 @@ using DependencyCallback =
3637
std::function<void(std::string_view, const sourcemeta::core::WeakPointer &,
3738
std::string_view, const sourcemeta::core::JSON &)>;
3839

40+
/// @ingroup bundle
41+
/// The strategies that the bundling process can follow
42+
enum class BundleMode : std::uint8_t {
43+
/// Embed every external reference, including any non-official
44+
/// meta-schemas that the schema or its dependencies declare, along
45+
/// with the dependencies of those meta-schemas
46+
NonOfficialMetaschemas,
47+
/// Embed every external reference, skipping meta-schema
48+
/// declarations entirely
49+
References
50+
};
51+
3952
/// @ingroup bundle
4053
///
4154
/// This function recursively traverses and reports the external references in a
@@ -117,7 +130,8 @@ auto dependencies(const sourcemeta::core::JSON &schema,
117130
/// })JSON");
118131
///
119132
/// sourcemeta::blaze::bundle(document,
120-
/// sourcemeta::blaze::schema_walker, test_resolver);
133+
/// sourcemeta::blaze::schema_walker, test_resolver,
134+
/// sourcemeta::blaze::BundleMode::NonOfficialMetaschemas);
121135
///
122136
/// const sourcemeta::core::JSON expected =
123137
/// sourcemeta::core::parse_json(R"JSON({
@@ -136,7 +150,7 @@ auto dependencies(const sourcemeta::core::JSON &schema,
136150
/// ```
137151
SOURCEMETA_BLAZE_BUNDLE_EXPORT
138152
auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
139-
const SchemaResolver &resolver,
153+
const SchemaResolver &resolver, const BundleMode mode,
140154
std::string_view default_dialect = "",
141155
std::string_view default_id = "",
142156
const std::optional<sourcemeta::core::Pointer> &default_container =
@@ -179,7 +193,8 @@ auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
179193
///
180194
/// const sourcemeta::core::JSON result =
181195
/// sourcemeta::blaze::bundle(document,
182-
/// sourcemeta::blaze::schema_walker, test_resolver);
196+
/// sourcemeta::blaze::schema_walker, test_resolver,
197+
/// sourcemeta::blaze::BundleMode::NonOfficialMetaschemas);
183198
///
184199
/// const sourcemeta::core::JSON expected =
185200
/// sourcemeta::core::parse_json(R"JSON({
@@ -199,8 +214,8 @@ auto bundle(sourcemeta::core::JSON &schema, const SchemaWalker &walker,
199214
SOURCEMETA_BLAZE_BUNDLE_EXPORT
200215
auto bundle(
201216
const sourcemeta::core::JSON &schema, const SchemaWalker &walker,
202-
const SchemaResolver &resolver, std::string_view default_dialect = "",
203-
std::string_view default_id = "",
217+
const SchemaResolver &resolver, const BundleMode mode,
218+
std::string_view default_dialect = "", std::string_view default_id = "",
204219
const std::optional<sourcemeta::core::Pointer> &default_container =
205220
std::nullopt,
206221
const SchemaFrame::Paths &paths = {sourcemeta::core::empty_weak_pointer})

src/codegen/codegen.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@ auto compile(const sourcemeta::core::JSON &input,
6262
// (1) Bundle the schema to resolve external references
6363
// --------------------------------------------------------------------------
6464

65-
auto schema{sourcemeta::blaze::bundle(input, walker, resolver,
66-
default_dialect, default_id)};
65+
auto schema{sourcemeta::blaze::bundle(
66+
input, walker, resolver, sourcemeta::blaze::BundleMode::References,
67+
default_dialect, default_id)};
6768

6869
// --------------------------------------------------------------------------
6970
// (2) Canonicalize the schema for easier analysis

src/compiler/compile.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,11 @@ auto compile(const sourcemeta::core::JSON &schema,
439439
assert(is_schema(schema));
440440

441441
// Make sure the input schema is bundled, otherwise we won't be able to
442-
// resolve remote references here
442+
// resolve remote references here. Meta-schemas are not needed, as we
443+
// can determine vocabularies through the resolver
443444
const sourcemeta::core::JSON result{sourcemeta::blaze::bundle(
444-
schema, walker, resolver, default_dialect, default_id)};
445+
schema, walker, resolver, sourcemeta::blaze::BundleMode::References,
446+
default_dialect, default_id)};
445447

446448
sourcemeta::blaze::SchemaFrame frame{
447449
sourcemeta::blaze::SchemaFrame::Mode::References};

src/configuration/fetch.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,10 @@ auto fetch_and_write(
117117

118118
try {
119119
const std::string default_dialect_value{default_dialect.value_or("")};
120-
sourcemeta::blaze::bundle(out_schema, sourcemeta::blaze::schema_walker,
121-
resolver, default_dialect_value, dependency_uri);
120+
sourcemeta::blaze::bundle(
121+
out_schema, sourcemeta::blaze::schema_walker, resolver,
122+
sourcemeta::blaze::BundleMode::NonOfficialMetaschemas,
123+
default_dialect_value, dependency_uri);
122124
} catch (...) {
123125
emit_event(callback, FetchEvent::Type::Error, dependency_uri,
124126
dependency_path, index, total, "Failed to bundle schema",

src/editor/include/sourcemeta/blaze/editor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace sourcemeta::blaze {
3535
///
3636
/// ```cpp
3737
/// #include <sourcemeta/core/json.h>
38+
/// #include <sourcemeta/blaze/bundle.h>
3839
/// #include <sourcemeta/blaze/foundation.h>
3940
/// #include <sourcemeta/blaze/editor.h>
4041
///
@@ -46,7 +47,8 @@ namespace sourcemeta::blaze {
4647
///
4748
/// sourcemeta::blaze::bundle(schema,
4849
/// sourcemeta::blaze::schema_walker,
49-
/// sourcemeta::blaze::schema_resolver);
50+
/// sourcemeta::blaze::schema_resolver,
51+
/// sourcemeta::blaze::BundleMode::NonOfficialMetaschemas);
5052
/// sourcemeta::blaze::for_editor(schema,
5153
/// sourcemeta::blaze::schema_walker,
5254
/// sourcemeta::blaze::schema_resolver);

0 commit comments

Comments
 (0)