Commit 0cb28cba authored by Hiroshige Hayashizaki's avatar Hiroshige Hayashizaki Committed by Commit Bot

[Import Maps] Make errors block the whole resolution, Blink-side

Reflects https://github.com/WICG/import-maps/pull/205.

This CL updates tests from #205.

To match the behavior with the updated spec,
this CL turns non-String values into `null` entries
(i.e. make whole resolution fail without further fallback),
instead of ignoring such entries.
Other aspects were already conformant with the updated spec
(i.e. weren't matching with the spec before #205).

This CL updates (test-only) import maps serialization code
so that it matches with the reference implementation, i.e.
dump `null` entries as `null` instead of `[]`.

This CL also updates spec comments.

Bug: 990561, https://github.com/WICG/import-maps/issues/184
Change-Id: Ifa2d04bf20fcef5575c14d135c328730ea09c454
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2037012
Commit-Queue: Hiroshige Hayashizaki <hiroshige@chromium.org>
Reviewed-by: default avatarKouhei Ueno <kouhei@chromium.org>
Cr-Commit-Position: refs/heads/master@{#740847}
parent 223fa11e
...@@ -109,7 +109,10 @@ KURL NormalizeValue(const String& key, ...@@ -109,7 +109,10 @@ KURL NormalizeValue(const String& key,
// <spec step="2.5.1">Report a warning to the console that the address was // <spec step="2.5.1">Report a warning to the console that the address was
// invalid.</spec> // invalid.</spec>
AddIgnoredValueMessage(logger, key, "Invalid URL: " + value_string); AddIgnoredValueMessage(logger, key, "Invalid URL: " + value_string);
// <spec step="2.5.2">Continue.</spec>
// <spec step="2.5.2">Set normalized[specifierKey] to null.</spec>
//
// <spec step="2.5.3">Continue.</spec>
return NullURL(); return NullURL();
case ParsedSpecifier::Type::kBare: case ParsedSpecifier::Type::kBare:
...@@ -128,7 +131,9 @@ KURL NormalizeValue(const String& key, ...@@ -128,7 +131,9 @@ KURL NormalizeValue(const String& key,
"Since specifierKey ended in a slash, so must the address: " + "Since specifierKey ended in a slash, so must the address: " +
value_string); value_string);
// <spec step="2.6.2">Continue.</spec> // <spec step="2.6.2">Set normalized[specifierKey] to null.</spec>
//
// <spec step="2.6.3">Continue.</spec>
return NullURL(); return NullURL();
} }
...@@ -256,10 +261,10 @@ ImportMap* ImportMap::Parse(const Modulator& modulator, ...@@ -256,10 +261,10 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
continue; continue;
} }
// <spec label="sort-and-normalize-scopes" step="2.5">Let // <spec label="sort-and-normalize-scopes" step="2.4">Let
// normalizedScopePrefix be the serialization of scopePrefixURL.</spec> // normalizedScopePrefix be the serialization of scopePrefixURL.</spec>
// //
// <spec label="sort-and-normalize-scopes" step="2.6">Set // <spec label="sort-and-normalize-scopes" step="2.5">Set
// normalized[normalizedScopePrefix] to the result of sorting and // normalized[normalizedScopePrefix] to the result of sorting and
// normalizing a specifier map given potentialSpecifierMap and // normalizing a specifier map given potentialSpecifierMap and
// baseURL.</spec> // baseURL.</spec>
...@@ -269,8 +274,8 @@ ImportMap* ImportMap::Parse(const Modulator& modulator, ...@@ -269,8 +274,8 @@ ImportMap* ImportMap::Parse(const Modulator& modulator,
support_builtin_modules, logger))); support_builtin_modules, logger)));
} }
// <spec label="sort-and-normalize-scopes" step="3">Return the result of // <spec label="sort-and-normalize-scopes" step="3">Return the result of
// sorting normalized, with an entry a being less than an entry b if a’s key // sorting normalized, with an entry a being less than an entry b if b’s key
// is longer or code unit less than b’s key.</spec> // is code unit less than a’s key.</spec>
std::sort(sorted_and_normalized_scopes.begin(), std::sort(sorted_and_normalized_scopes.begin(),
sorted_and_normalized_scopes.end(), sorted_and_normalized_scopes.end(),
[](const ScopeEntryType& a, const ScopeEntryType& b) { [](const ScopeEntryType& a, const ScopeEntryType& b) {
...@@ -314,37 +319,6 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap( ...@@ -314,37 +319,6 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
Vector<KURL> values; Vector<KURL> values;
switch (entry.second->GetType()) { switch (entry.second->GetType()) {
case JSONValue::ValueType::kTypeNull:
if (!support_builtin_modules) {
// <spec step="2.3">If value is not a string, then:</spec>
//
// <spec step="2.3.1">Report a warning to the console that addresses
// must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
// <spec step="2.3.2">Continue.</spec>
continue;
}
// [Spec w/ Built-in] Otherwise, if value is null, then set
// normalized[normalizedSpecifierKey] to a new empty list.
break;
case JSONValue::ValueType::kTypeBoolean:
case JSONValue::ValueType::kTypeInteger:
case JSONValue::ValueType::kTypeDouble:
case JSONValue::ValueType::kTypeObject:
// <spec step="2.3">If value is not a string, then:</spec>
//
// <spec step="2.3.1">Report a warning to the console that addresses
// must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
// <spec step="2.3.2">Continue.</spec>
//
// By continuing here, we leave |normalized[normalized_specifier_key]|
// unset, and continue processing.
continue;
case JSONValue::ValueType::kTypeString: { case JSONValue::ValueType::kTypeString: {
// Steps 2.4-2.6 are implemented in NormalizeValue(). // Steps 2.4-2.6 are implemented in NormalizeValue().
String value_string; String value_string;
...@@ -362,6 +336,22 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap( ...@@ -362,6 +336,22 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
break; break;
} }
case JSONValue::ValueType::kTypeNull:
case JSONValue::ValueType::kTypeBoolean:
case JSONValue::ValueType::kTypeInteger:
case JSONValue::ValueType::kTypeDouble:
case JSONValue::ValueType::kTypeObject:
// <spec step="2.3">If value is not a string, then:</spec>
//
// <spec step="2.3.1">Report a warning to the console that addresses
// must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
// <spec step="2.3.2">Set normalized[specifierKey] to null.</spec>
//
// <spec step="2.3.3">Continue.</spec>
break;
case JSONValue::ValueType::kTypeArray: { case JSONValue::ValueType::kTypeArray: {
if (!support_builtin_modules) { if (!support_builtin_modules) {
// <spec step="2.3">If value is not a string, then:</spec> // <spec step="2.3">If value is not a string, then:</spec>
...@@ -370,8 +360,10 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap( ...@@ -370,8 +360,10 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
// must be strings.</spec> // must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, "Invalid value type."); AddIgnoredValueMessage(logger, entry.first, "Invalid value type.");
// <spec step="2.3.2">Continue.</spec> // <spec step="2.3.2">Set normalized[specifierKey] to null.</spec>
continue; //
// <spec step="2.3.3">Continue.</spec>
break;
} }
// [Spec w/ Built-in] Otherwise, if value is a list, then set // [Spec w/ Built-in] Otherwise, if value is a list, then set
...@@ -392,7 +384,7 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap( ...@@ -392,7 +384,7 @@ ImportMap::SpecifierMap ImportMap::SortAndNormalizeSpecifierMap(
// must be strings.</spec> // must be strings.</spec>
AddIgnoredValueMessage(logger, entry.first, AddIgnoredValueMessage(logger, entry.first,
"Non-string in the value."); "Non-string in the value.");
// <spec step="2.3.2">Continue.</spec> // <spec step="2.3.3">Continue.</spec>
continue; continue;
} }
KURL value = NormalizeValue(entry.first, value_string, base_url, KURL value = NormalizeValue(entry.first, value_string, base_url,
...@@ -453,7 +445,8 @@ base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix( ...@@ -453,7 +445,8 @@ base::Optional<ImportMap::MatchResult> ImportMap::MatchPrefix(
// https://github.com/WICG/import-maps/issues/102 // https://github.com/WICG/import-maps/issues/102
base::Optional<MatchResult> best_match; base::Optional<MatchResult> best_match;
// <spec step="1">For each specifierKey → address of specifierMap,</spec> // <spec step="1">For each specifierKey → resolutionResult of
// specifierMap,</spec>
for (auto it = specifier_map.begin(); it != specifier_map.end(); ++it) { for (auto it = specifier_map.begin(); it != specifier_map.end(); ++it) {
// <spec step="1.2">If specifierKey ends with U+002F (/) and // <spec step="1.2">If specifierKey ends with U+002F (/) and
// normalizedSpecifier starts with specifierKey, then:</spec> // normalizedSpecifier starts with specifierKey, then:</spec>
...@@ -530,7 +523,7 @@ base::Optional<KURL> ImportMap::ResolveImportsMatch( ...@@ -530,7 +523,7 @@ base::Optional<KURL> ImportMap::ResolveImportsMatch(
DCHECK(debug_message); DCHECK(debug_message);
const String key = parsed_specifier.GetImportMapKeyString(); const String key = parsed_specifier.GetImportMapKeyString();
// <spec step="1.1">If specifierKey is normalizedSpecifier, then ...</spec> // <spec step="1.1">If specifierKey is normalizedSpecifier, then:</spec>
MatchResult exact = specifier_map.find(key); MatchResult exact = specifier_map.find(key);
if (exact != specifier_map.end()) { if (exact != specifier_map.end()) {
return ResolveImportsMatchInternal(key, exact, debug_message); return ResolveImportsMatchInternal(key, exact, debug_message);
...@@ -552,19 +545,18 @@ base::Optional<KURL> ImportMap::ResolveImportsMatchInternal( ...@@ -552,19 +545,18 @@ base::Optional<KURL> ImportMap::ResolveImportsMatchInternal(
const String& key, const String& key,
const MatchResult& matched, const MatchResult& matched,
String* debug_message) const { String* debug_message) const {
// <spec step="1.2.1">Let afterPrefix be the portion of normalizedSpecifier // <spec step="1.2.3">Let afterPrefix be the portion of normalizedSpecifier
// after the initial specifierKey prefix.</spec> // after the initial specifierKey prefix.</spec>
const String after_prefix = key.Substring(matched->key.length()); const String after_prefix = key.Substring(matched->key.length());
for (const KURL& value : matched->value) { for (const KURL& value : matched->value) {
// <spec step="1.1">If specifierKey is normalizedSpecifier, then return // <spec step="1.1">If specifierKey is normalizedSpecifier, then:</spec>
// address.</spec>
// //
// <spec step="1.2">If specifierKey ends with U+002F (/) and // <spec step="1.2">If specifierKey ends with U+002F (/) and
// normalizedSpecifier starts with specifierKey, then:</spec> // normalizedSpecifier starts with specifierKey, then:</spec>
// //
// <spec step="1.2.3">Let url be the result of parsing afterPrefix relative // <spec step="1.2.5">Let url be the result of parsing afterPrefix relative
// to the base URL address.</spec> // to the base URL resolutionResult.</spec>
const KURL url = after_prefix.IsEmpty() ? value : KURL(value, after_prefix); const KURL url = after_prefix.IsEmpty() ? value : KURL(value, after_prefix);
// [Spec w/ Built-in] Return url0, if moduleMap[url0] exists; otherwise, // [Spec w/ Built-in] Return url0, if moduleMap[url0] exists; otherwise,
...@@ -578,9 +570,9 @@ base::Optional<KURL> ImportMap::ResolveImportsMatchInternal( ...@@ -578,9 +570,9 @@ base::Optional<KURL> ImportMap::ResolveImportsMatchInternal(
matched->key + "\" and is mapped to " + matched->key + "\" and is mapped to " +
url.ElidedString(); url.ElidedString();
// <spec step="1.2.4">If url is failure, then return null.</spec> // <spec step="1.2.6">If url is failure, then throw ...</spec>
// //
// <spec step="1.2.5">Return url.</spec> // <spec step="1.2.8">Return url.</spec>
return url; return url;
} }
} }
...@@ -615,7 +607,7 @@ static void SpecifierMapToString(StringBuilder& builder, ...@@ -615,7 +607,7 @@ static void SpecifierMapToString(StringBuilder& builder,
builder.Append("]"); builder.Append("]");
} else { } else {
if (it.value.size() == 0) { if (it.value.size() == 0) {
builder.Append("[]"); builder.Append("null");
} else { } else {
DCHECK_EQ(it.value.size(), 1u); DCHECK_EQ(it.value.size(), 1u);
builder.Append(it.value[0].GetString().EncodeForDebugging()); builder.Append(it.value[0].GetString().EncodeForDebugging());
......
This is a testharness.js-based test.
PASS Invalid JSON
PASS Mismatching the top-level schema / should throw for top-level non-objects
PASS Mismatching the top-level schema / should throw if imports is a non-object
PASS Mismatching the top-level schema / should throw if scopes is a non-object
PASS Mismatching the top-level schema / should ignore unspecified top-level entries
FAIL Mismatching the specifier map schema / should ignore entries where the address is not a string, array, or null assert_equals: expected "{\"imports\":{\"bar\":[\"https://example.com/\"]},\"scopes\":{}}" but got "{\"imports\":{\"bar\":[\"https://example.com/\"],\"foo\":[]},\"scopes\":{}}"
PASS Mismatching the specifier map schema / should ignore entries where the specifier key is an empty string
PASS Mismatching the specifier map schema / should ignore members of an address array that are not strings
PASS Mismatching the specifier map schema / should throw if a scope's value is not an object
PASS Normalization / should normalize empty import maps to have imports and scopes keys
PASS Normalization / should normalize an import map without imports to have imports
PASS Normalization / should normalize an import map without scopes to have scopes
PASS Normalization / should normalize addresses to arrays
Harness: the test ran to completion.
...@@ -12,12 +12,12 @@ PASS Test helper: fetching and sanity checking test JSON: resources/parsing-scop ...@@ -12,12 +12,12 @@ PASS Test helper: fetching and sanity checking test JSON: resources/parsing-scop
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-specifier-keys.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-specifier-keys.json
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-trailing-slashes.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-trailing-slashes.json
FAIL Absolute URL addresses: should only accept absolute URL addresses with fetch schemes assert_equals: expected "{\"imports\":{\"about\":\"about:good\",\"blob\":\"blob:good\",\"data\":\"data:good\",\"file\":\"file:///good\",\"filesystem\":\"filesystem:http://example.com/good/\",\"ftp\":\"ftp://good/\",\"http\":\"http://good/\",\"https\":\"https://good/\",\"import\":\"import:bad\",\"javascript\":\"javascript:bad\",\"mailto\":\"mailto:bad\",\"wss\":\"wss://bad/\"},\"scopes\":{}}" but got "{\"imports\":{\"about\":[\"about:good\"],\"blob\":[\"blob:good\"],\"data\":[\"data:good\"],\"file\":[\"file:///good\"],\"filesystem\":[\"filesystem:http://example.com/good/\"],\"ftp\":[\"ftp://good/\"],\"http\":[\"http://good/\"],\"https\":[\"https://good/\"],\"import\":[\"import:bad\"],\"javascript\":[\"javascript:bad\"],\"mailto\":[\"mailto:bad\"],\"wss\":[\"wss://bad/\"]},\"scopes\":{}}" FAIL Absolute URL addresses: should only accept absolute URL addresses with fetch schemes assert_equals: expected "{\"imports\":{\"about\":\"about:good\",\"blob\":\"blob:good\",\"data\":\"data:good\",\"file\":\"file:///good\",\"filesystem\":\"filesystem:http://example.com/good/\",\"ftp\":\"ftp://good/\",\"http\":\"http://good/\",\"https\":\"https://good/\",\"import\":\"import:bad\",\"javascript\":\"javascript:bad\",\"mailto\":\"mailto:bad\",\"wss\":\"wss://bad/\"},\"scopes\":{}}" but got "{\"imports\":{\"about\":[\"about:good\"],\"blob\":[\"blob:good\"],\"data\":[\"data:good\"],\"file\":[\"file:///good\"],\"filesystem\":[\"filesystem:http://example.com/good/\"],\"ftp\":[\"ftp://good/\"],\"http\":[\"http://good/\"],\"https\":[\"https://good/\"],\"import\":[\"import:bad\"],\"javascript\":[\"javascript:bad\"],\"mailto\":[\"mailto:bad\"],\"wss\":[\"wss://bad/\"]},\"scopes\":{}}"
FAIL Absolute URL addresses: should parse absolute URLs, ignoring unparseable ones assert_equals: expected "{\"imports\":{\"invalidButParseable1\":\"https://example.org/\",\"invalidButParseable2\":\"https://example.com///\",\"percentDecoding\":\"https://example.com/\",\"prettyNormal\":\"https://example.net/\"},\"scopes\":{}}" but got "{\"imports\":{\"invalidButParseable1\":[\"https://example.org/\"],\"invalidButParseable2\":[\"https://example.com///\"],\"percentDecoding\":[\"https://example.com/\"],\"prettyNormal\":[\"https://example.net/\"],\"unparseable2\":[],\"unparseable3\":[]},\"scopes\":{}}" FAIL Absolute URL addresses: should parse absolute URLs, ignoring unparseable ones assert_equals: expected "{\"imports\":{\"invalidButParseable1\":\"https://example.org/\",\"invalidButParseable2\":\"https://example.com///\",\"percentDecoding\":\"https://example.com/\",\"prettyNormal\":\"https://example.net/\",\"unparseable2\":null,\"unparseable3\":null},\"scopes\":{}}" but got "{\"imports\":{\"invalidButParseable1\":[\"https://example.org/\"],\"invalidButParseable2\":[\"https://example.com///\"],\"percentDecoding\":[\"https://example.com/\"],\"prettyNormal\":[\"https://example.net/\"],\"unparseable2\":[],\"unparseable3\":[]},\"scopes\":{}}"
FAIL Other invalid addresses: should ignore unprefixed strings that are not absolute URLs assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"foo1\":[],\"foo2\":[],\"foo3\":[],\"foo4\":[],\"foo5\":[]},\"scopes\":{}}" FAIL Other invalid addresses: should ignore unprefixed strings that are not absolute URLs assert_equals: expected "{\"imports\":{\"foo1\":null,\"foo2\":null,\"foo3\":null,\"foo4\":null,\"foo5\":null},\"scopes\":{}}" but got "{\"imports\":{\"foo1\":[],\"foo2\":[],\"foo3\":[],\"foo4\":[],\"foo5\":[]},\"scopes\":{}}"
FAIL Relative URL-like addresses: should accept strings prefixed with ./, ../, or / assert_equals: expected "{\"imports\":{\"dotDotSlash\":\"https://base.example/path1/foo\",\"dotSlash\":\"https://base.example/path1/path2/foo\",\"slash\":\"https://base.example/foo\"},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[\"https://base.example/path1/foo\"],\"dotSlash\":[\"https://base.example/path1/path2/foo\"],\"slash\":[\"https://base.example/foo\"]},\"scopes\":{}}" FAIL Relative URL-like addresses: should accept strings prefixed with ./, ../, or / assert_equals: expected "{\"imports\":{\"dotDotSlash\":\"https://base.example/path1/foo\",\"dotSlash\":\"https://base.example/path1/path2/foo\",\"slash\":\"https://base.example/foo\"},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[\"https://base.example/path1/foo\"],\"dotSlash\":[\"https://base.example/path1/path2/foo\"],\"slash\":[\"https://base.example/foo\"]},\"scopes\":{}}"
FAIL Relative URL-like addresses: should not accept strings prefixed with ./, ../, or / for data: base URLs assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[],\"dotSlash\":[],\"slash\":[]},\"scopes\":{}}" FAIL Relative URL-like addresses: should not accept strings prefixed with ./, ../, or / for data: base URLs assert_equals: expected "{\"imports\":{\"dotDotSlash\":null,\"dotSlash\":null,\"slash\":null},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[],\"dotSlash\":[],\"slash\":[]},\"scopes\":{}}"
FAIL Relative URL-like addresses: should accept the literal strings ./, ../, or / with no suffix assert_equals: expected "{\"imports\":{\"dotDotSlash\":\"https://base.example/path1/\",\"dotSlash\":\"https://base.example/path1/path2/\",\"slash\":\"https://base.example/\"},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[\"https://base.example/path1/\"],\"dotSlash\":[\"https://base.example/path1/path2/\"],\"slash\":[\"https://base.example/\"]},\"scopes\":{}}" FAIL Relative URL-like addresses: should accept the literal strings ./, ../, or / with no suffix assert_equals: expected "{\"imports\":{\"dotDotSlash\":\"https://base.example/path1/\",\"dotSlash\":\"https://base.example/path1/path2/\",\"slash\":\"https://base.example/\"},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[\"https://base.example/path1/\"],\"dotSlash\":[\"https://base.example/path1/path2/\"],\"slash\":[\"https://base.example/\"]},\"scopes\":{}}"
FAIL Relative URL-like addresses: should ignore percent-encoded variants of ./, ../, or / assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash1\":[],\"dotDotSlash2\":[],\"dotDotSlash3\":[],\"dotSlash1\":[],\"dotSlash2\":[],\"dotSlash3\":[],\"slash2\":[]},\"scopes\":{}}" FAIL Relative URL-like addresses: should ignore percent-encoded variants of ./, ../, or / assert_equals: expected "{\"imports\":{\"dotDotSlash1\":null,\"dotDotSlash2\":null,\"dotDotSlash3\":null,\"dotSlash1\":null,\"dotSlash2\":null,\"dotSlash3\":null,\"slash2\":null},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash1\":[],\"dotDotSlash2\":[],\"dotDotSlash3\":[],\"dotSlash1\":[],\"dotSlash2\":[],\"dotSlash3\":[],\"slash2\":[]},\"scopes\":{}}"
PASS Invalid JSON PASS Invalid JSON
PASS Normalization: should normalize empty import maps to have imports and scopes keys PASS Normalization: should normalize empty import maps to have imports and scopes keys
PASS Normalization: should normalize an import map without imports to have imports PASS Normalization: should normalize an import map without imports to have imports
...@@ -27,7 +27,7 @@ PASS Mismatching scopes schema: should throw if a scope's value is not an object ...@@ -27,7 +27,7 @@ PASS Mismatching scopes schema: should throw if a scope's value is not an object
PASS Mismatching scopes schema: should throw if a scope's value is not an object: number PASS Mismatching scopes schema: should throw if a scope's value is not an object: number
PASS Mismatching scopes schema: should throw if a scope's value is not an object: string PASS Mismatching scopes schema: should throw if a scope's value is not an object: string
PASS Mismatching scopes schema: should throw if a scope's value is not an object: array PASS Mismatching scopes schema: should throw if a scope's value is not an object: array
FAIL Mismatching the specifier map schema: should ignore entries where the address is not a string assert_equals: expected "{\"imports\":{\"string\":\"https://example.com/\"},\"scopes\":{}}" but got "{\"imports\":{\"array\":[],\"array2\":[\"https://example.com/\"],\"null\":[],\"string\":[\"https://example.com/\"]},\"scopes\":{}}" FAIL Mismatching the specifier map schema: should ignore entries where the address is not a string assert_equals: expected "{\"imports\":{\"array\":null,\"array2\":null,\"boolean\":null,\"null\":null,\"number\":null,\"object\":null,\"string\":\"https://example.com/\"},\"scopes\":{}}" but got "{\"imports\":{\"array\":[],\"array2\":[\"https://example.com/\"],\"boolean\":[],\"null\":[],\"number\":[],\"object\":[],\"string\":[\"https://example.com/\"]},\"scopes\":{}}"
PASS Mismatching the specifier map schema: should ignore entries where the specifier key is an empty string PASS Mismatching the specifier map schema: should ignore entries where the specifier key is an empty string
PASS Mismatching the top-level schema: should throw for top-level non-objects: null PASS Mismatching the top-level schema: should throw for top-level non-objects: null
PASS Mismatching the top-level schema: should throw for top-level non-objects: boolean PASS Mismatching the top-level schema: should throw for top-level non-objects: boolean
...@@ -66,6 +66,6 @@ FAIL Absolute URL specifier keys should accept all absolute URL specifier keys, ...@@ -66,6 +66,6 @@ FAIL Absolute URL specifier keys should accept all absolute URL specifier keys,
FAIL Absolute URL specifier keys should parse absolute URLs, treating unparseable ones as bare specifiers assert_equals: expected "{\"imports\":{\"http://[www.example.com]/\":\"https://base.example/unparseable3/\",\"https://example.com/\":\"https://base.example/percentDecoding/\",\"https://example.com///\":\"https://base.example/invalidButParseable2/\",\"https://example.com:demo\":\"https://base.example/unparseable2\",\"https://example.net/\":\"https://base.example/prettyNormal/\",\"https://example.org/\":\"https://base.example/invalidButParseable1/\"},\"scopes\":{}}" but got "{\"imports\":{\"http://[www.example.com]/\":[\"https://base.example/unparseable3/\"],\"https://example.com/\":[\"https://base.example/percentDecoding/\"],\"https://example.com///\":[\"https://base.example/invalidButParseable2/\"],\"https://example.com:demo\":[\"https://base.example/unparseable2\"],\"https://example.net/\":[\"https://base.example/prettyNormal/\"],\"https://example.org/\":[\"https://base.example/invalidButParseable1/\"]},\"scopes\":{}}" FAIL Absolute URL specifier keys should parse absolute URLs, treating unparseable ones as bare specifiers assert_equals: expected "{\"imports\":{\"http://[www.example.com]/\":\"https://base.example/unparseable3/\",\"https://example.com/\":\"https://base.example/percentDecoding/\",\"https://example.com///\":\"https://base.example/invalidButParseable2/\",\"https://example.com:demo\":\"https://base.example/unparseable2\",\"https://example.net/\":\"https://base.example/prettyNormal/\",\"https://example.org/\":\"https://base.example/invalidButParseable1/\"},\"scopes\":{}}" but got "{\"imports\":{\"http://[www.example.com]/\":[\"https://base.example/unparseable3/\"],\"https://example.com/\":[\"https://base.example/percentDecoding/\"],\"https://example.com///\":[\"https://base.example/invalidButParseable2/\"],\"https://example.com:demo\":[\"https://base.example/unparseable2\"],\"https://example.net/\":[\"https://base.example/prettyNormal/\"],\"https://example.org/\":[\"https://base.example/invalidButParseable1/\"]},\"scopes\":{}}"
FAIL Specifier keys should be sort correctly (issue #181) - Test #1 assert_equals: expected "{\"imports\":{\"https://example.com/a\":\"https://example.com/a\",\"https://example.com/aaa\":\"https://example.com/aaa\"},\"scopes\":{}}" but got "{\"imports\":{\"https://example.com/a\":[\"https://example.com/a\"],\"https://example.com/aaa\":[\"https://example.com/aaa\"]},\"scopes\":{}}" FAIL Specifier keys should be sort correctly (issue #181) - Test #1 assert_equals: expected "{\"imports\":{\"https://example.com/a\":\"https://example.com/a\",\"https://example.com/aaa\":\"https://example.com/aaa\"},\"scopes\":{}}" but got "{\"imports\":{\"https://example.com/a\":[\"https://example.com/a\"],\"https://example.com/aaa\":[\"https://example.com/aaa\"]},\"scopes\":{}}"
FAIL Specifier keys should be sort correctly (issue #181) - Test #2 assert_equals: expected "{\"imports\":{\"https://example.com/a\":\"https://example.com/a\",\"https://example.com/aaa\":\"https://example.com/aaa\"},\"scopes\":{}}" but got "{\"imports\":{\"https://example.com/a\":[\"https://example.com/a\"],\"https://example.com/aaa\":[\"https://example.com/aaa\"]},\"scopes\":{}}" FAIL Specifier keys should be sort correctly (issue #181) - Test #2 assert_equals: expected "{\"imports\":{\"https://example.com/a\":\"https://example.com/a\",\"https://example.com/aaa\":\"https://example.com/aaa\"},\"scopes\":{}}" but got "{\"imports\":{\"https://example.com/a\":[\"https://example.com/a\"],\"https://example.com/aaa\":[\"https://example.com/aaa\"]},\"scopes\":{}}"
FAIL Failing addresses: mismatched trailing slashes assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"trailer/\":[]},\"scopes\":{}}" FAIL Failing addresses: mismatched trailing slashes assert_equals: expected "{\"imports\":{\"trailer/\":null},\"scopes\":{}}" but got "{\"imports\":{\"trailer/\":[]},\"scopes\":{}}"
Harness: the test ran to completion. Harness: the test ran to completion.
...@@ -15,6 +15,7 @@ for (const json of [ ...@@ -15,6 +15,7 @@ for (const json of [
'resources/data-base-url.json', 'resources/data-base-url.json',
'resources/scopes-exact-vs-prefix.json', 'resources/scopes-exact-vs-prefix.json',
'resources/overlapping-entries.json', 'resources/overlapping-entries.json',
'resources/resolving-null.json',
]) { ]) {
promise_test(() => promise_test(() =>
runTestsFromJSON(json), runTestsFromJSON(json),
......
...@@ -51,6 +51,8 @@ ...@@ -51,6 +51,8 @@
"importMapBaseURL": "https://base.example/path1/path2/path3", "importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": { "imports": {
"unparseable2": null,
"unparseable3": null,
"invalidButParseable1": "https://example.org/", "invalidButParseable1": "https://example.org/",
"invalidButParseable2": "https://example.com///", "invalidButParseable2": "https://example.com///",
"prettyNormal": "https://example.net/", "prettyNormal": "https://example.net/",
......
...@@ -13,7 +13,13 @@ ...@@ -13,7 +13,13 @@
}, },
"importMapBaseURL": "https://base.example/path1/path2/path3", "importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": {}, "imports": {
"foo1": null,
"foo2": null,
"foo3": null,
"foo4": null,
"foo5": null
},
"scopes": {} "scopes": {}
} }
} }
......
...@@ -29,7 +29,11 @@ ...@@ -29,7 +29,11 @@
}, },
"importMapBaseURL": "data:text/html,test", "importMapBaseURL": "data:text/html,test",
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": {}, "imports": {
"dotSlash": null,
"dotDotSlash": null,
"slash": null
},
"scopes": {} "scopes": {}
} }
}, },
...@@ -65,7 +69,15 @@ ...@@ -65,7 +69,15 @@
}, },
"importMapBaseURL": "https://base.example/path1/path2/path3", "importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": {}, "imports": {
"dotSlash1": null,
"dotDotSlash1": null,
"dotSlash2": null,
"dotDotSlash2": null,
"slash2": null,
"dotSlash3": null,
"dotDotSlash3": null
},
"scopes": {} "scopes": {}
} }
} }
......
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
}, },
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": { "imports": {
"null": null,
"boolean": null,
"number": null,
"object": null,
"array": null,
"array2": null,
"string": "https://example.com/" "string": "https://example.com/"
}, },
"scopes": {} "scopes": {}
......
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
}, },
"importMapBaseURL": "https://base.example/path1/path2/path3", "importMapBaseURL": "https://base.example/path1/path2/path3",
"expectedParsedImportMap": { "expectedParsedImportMap": {
"imports": {}, "imports": {
"trailer/": null
},
"scopes": {} "scopes": {}
} }
} }
{
"importMapBaseURL": "https://example.com/app/index.html",
"baseURL": "https://example.com/js/app.mjs",
"name": "Entries with errors shouldn't allow fallback",
"tests": {
"No fallback to less-specific prefixes": {
"importMap": {
"imports": {
"null/": "/1/",
"null/b/": null,
"null/b/c/": "/1/2/",
"invalid-url/": "/1/",
"invalid-url/b/": "https://:invalid-url:/",
"invalid-url/b/c/": "/1/2/",
"without-trailing-slashes/": "/1/",
"without-trailing-slashes/b/": "/x",
"without-trailing-slashes/b/c/": "/1/2/",
"prefix-resolution-error/": "/1/",
"prefix-resolution-error/b/": "data:text/javascript,/",
"prefix-resolution-error/b/c/": "/1/2/"
}
},
"expectedResults": {
"null/x": "https://example.com/1/x",
"null/b/x": null,
"null/b/c/x": "https://example.com/1/2/x",
"invalid-url/x": "https://example.com/1/x",
"invalid-url/b/x": null,
"invalid-url/b/c/x": "https://example.com/1/2/x",
"without-trailing-slashes/x": "https://example.com/1/x",
"without-trailing-slashes/b/x": null,
"without-trailing-slashes/b/c/x": "https://example.com/1/2/x",
"prefix-resolution-error/x": "https://example.com/1/x",
"prefix-resolution-error/b/x": null,
"prefix-resolution-error/b/c/x": "https://example.com/1/2/x"
}
},
"No fallback to less-specific scopes": {
"importMap": {
"imports": {
"null": "https://example.com/a",
"invalid-url": "https://example.com/b",
"without-trailing-slashes/": "https://example.com/c/",
"prefix-resolution-error/": "https://example.com/d/"
},
"scopes": {
"/js/": {
"null": null,
"invalid-url": "https://:invalid-url:/",
"without-trailing-slashes/": "/x",
"prefix-resolution-error/": "data:text/javascript,/"
}
}
},
"expectedResults": {
"null": null,
"invalid-url": null,
"without-trailing-slashes/x": null,
"prefix-resolution-error/x": null
}
},
"No fallback to absolute URL parsing": {
"importMap": {
"imports": {},
"scopes": {
"/js/": {
"https://example.com/null": null,
"https://example.com/invalid-url": "https://:invalid-url:/",
"https://example.com/without-trailing-slashes/": "/x",
"https://example.com/prefix-resolution-error/": "data:text/javascript,/"
}
}
},
"expectedResults": {
"https://example.com/null": null,
"https://example.com/invalid-url": null,
"https://example.com/without-trailing-slashes/x": null,
"https://example.com/prefix-resolution-error/x": null
}
}
}
}
This is a testharness.js-based test. This is a testharness.js-based test.
Found 67 tests; 62 PASS, 5 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses-absolute.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses-absolute.json
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses-invalid.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses-invalid.json
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-addresses.json
...@@ -12,12 +11,12 @@ PASS Test helper: fetching and sanity checking test JSON: resources/parsing-scop ...@@ -12,12 +11,12 @@ PASS Test helper: fetching and sanity checking test JSON: resources/parsing-scop
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-specifier-keys.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-specifier-keys.json
PASS Test helper: fetching and sanity checking test JSON: resources/parsing-trailing-slashes.json PASS Test helper: fetching and sanity checking test JSON: resources/parsing-trailing-slashes.json
PASS Absolute URL addresses: should only accept absolute URL addresses with fetch schemes PASS Absolute URL addresses: should only accept absolute URL addresses with fetch schemes
FAIL Absolute URL addresses: should parse absolute URLs, ignoring unparseable ones assert_equals: expected "{\"imports\":{\"invalidButParseable1\":\"https://example.org/\",\"invalidButParseable2\":\"https://example.com///\",\"percentDecoding\":\"https://example.com/\",\"prettyNormal\":\"https://example.net/\"},\"scopes\":{}}" but got "{\"imports\":{\"invalidButParseable1\":\"https://example.org/\",\"invalidButParseable2\":\"https://example.com///\",\"percentDecoding\":\"https://example.com/\",\"prettyNormal\":\"https://example.net/\",\"unparseable2\":[],\"unparseable3\":[]},\"scopes\":{}}" PASS Absolute URL addresses: should parse absolute URLs, ignoring unparseable ones
FAIL Other invalid addresses: should ignore unprefixed strings that are not absolute URLs assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"foo1\":[],\"foo2\":[],\"foo3\":[],\"foo4\":[],\"foo5\":[]},\"scopes\":{}}" PASS Other invalid addresses: should ignore unprefixed strings that are not absolute URLs
PASS Relative URL-like addresses: should accept strings prefixed with ./, ../, or / PASS Relative URL-like addresses: should accept strings prefixed with ./, ../, or /
FAIL Relative URL-like addresses: should not accept strings prefixed with ./, ../, or / for data: base URLs assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash\":[],\"dotSlash\":[],\"slash\":[]},\"scopes\":{}}" PASS Relative URL-like addresses: should not accept strings prefixed with ./, ../, or / for data: base URLs
PASS Relative URL-like addresses: should accept the literal strings ./, ../, or / with no suffix PASS Relative URL-like addresses: should accept the literal strings ./, ../, or / with no suffix
FAIL Relative URL-like addresses: should ignore percent-encoded variants of ./, ../, or / assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"dotDotSlash1\":[],\"dotDotSlash2\":[],\"dotDotSlash3\":[],\"dotSlash1\":[],\"dotSlash2\":[],\"dotSlash3\":[],\"slash2\":[]},\"scopes\":{}}" PASS Relative URL-like addresses: should ignore percent-encoded variants of ./, ../, or /
PASS Invalid JSON PASS Invalid JSON
PASS Normalization: should normalize empty import maps to have imports and scopes keys PASS Normalization: should normalize empty import maps to have imports and scopes keys
PASS Normalization: should normalize an import map without imports to have imports PASS Normalization: should normalize an import map without imports to have imports
...@@ -66,6 +65,6 @@ PASS Absolute URL specifier keys should accept all absolute URL specifier keys, ...@@ -66,6 +65,6 @@ PASS Absolute URL specifier keys should accept all absolute URL specifier keys,
PASS Absolute URL specifier keys should parse absolute URLs, treating unparseable ones as bare specifiers PASS Absolute URL specifier keys should parse absolute URLs, treating unparseable ones as bare specifiers
PASS Specifier keys should be sort correctly (issue #181) - Test #1 PASS Specifier keys should be sort correctly (issue #181) - Test #1
PASS Specifier keys should be sort correctly (issue #181) - Test #2 PASS Specifier keys should be sort correctly (issue #181) - Test #2
FAIL Failing addresses: mismatched trailing slashes assert_equals: expected "{\"imports\":{},\"scopes\":{}}" but got "{\"imports\":{\"trailer/\":[]},\"scopes\":{}}" PASS Failing addresses: mismatched trailing slashes
Harness: the test ran to completion. Harness: the test ran to completion.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment