mirror of
https://github.com/denoland/deno
synced 2024-08-25 11:07:24 +00:00
fix(ext/webidl): correctly apply [SymbolToStringTag] to interfaces (#11851)
Co-authored-by: Luca Casonato <hello@lcas.dev> Co-authored-by: Yoshiya Hinosawa <stibium121@gmail.com>
This commit is contained in:
parent
9705efd419
commit
46245b830a
|
@ -27,7 +27,6 @@
|
|||
StringFromCharCode,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
WeakMap,
|
||||
WeakMapPrototypeGet,
|
||||
WeakMapPrototypeSet,
|
||||
|
@ -270,10 +269,6 @@
|
|||
return this[_algorithm];
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "CryptoKey";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
return `${this.constructor.name} ${
|
||||
inspect({
|
||||
|
@ -1570,10 +1565,6 @@
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "SubtleCrypto";
|
||||
}
|
||||
}
|
||||
|
||||
async function generateKey(normalizedAlgorithm, extractable, usages) {
|
||||
|
@ -2027,6 +2018,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(SubtleCrypto);
|
||||
const subtle = webidl.createBranded(SubtleCrypto);
|
||||
|
||||
class Crypto {
|
||||
|
@ -2079,10 +2071,6 @@
|
|||
return subtle;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Crypto";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
return `${this.constructor.name} ${inspect({})}`;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolIterator,
|
||||
SymbolToStringTag,
|
||||
StringPrototypeReplaceAll,
|
||||
StringPrototypeIncludes,
|
||||
TypeError,
|
||||
|
@ -411,10 +410,6 @@
|
|||
}
|
||||
return `Headers ${inspect(headers)}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Headers";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.mixinPairIterable("Headers", Headers, _iterableHeaders, 0, 1);
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
MapPrototypeSet,
|
||||
MathRandom,
|
||||
Symbol,
|
||||
SymbolToStringTag,
|
||||
StringFromCharCode,
|
||||
StringPrototypeTrim,
|
||||
StringPrototypeSlice,
|
||||
|
@ -72,10 +71,6 @@
|
|||
*/
|
||||
|
||||
class FormData {
|
||||
get [SymbolToStringTag]() {
|
||||
return "FormData";
|
||||
}
|
||||
|
||||
/** @type {FormDataEntry[]} */
|
||||
[entryList] = [];
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
RegExpPrototypeTest,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
|
@ -397,10 +396,6 @@
|
|||
);
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Request";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
return inspect(consoleInternal.createFilteredInspectProxy({
|
||||
object: this,
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
RegExpPrototypeTest,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
|
@ -373,10 +372,6 @@
|
|||
return second;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Response";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
return inspect(consoleInternal.createFilteredInspectProxy({
|
||||
object: this,
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
ObjectKeys,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
|
@ -192,8 +191,6 @@
|
|||
|
||||
const _detail = Symbol("[[detail]]");
|
||||
class PerformanceMark extends PerformanceEntry {
|
||||
[SymbolToStringTag] = "PerformanceMark";
|
||||
|
||||
[_detail] = null;
|
||||
|
||||
get detail() {
|
||||
|
@ -261,8 +258,6 @@
|
|||
webidl.configurePrototype(PerformanceMark);
|
||||
|
||||
class PerformanceMeasure extends PerformanceEntry {
|
||||
[SymbolToStringTag] = "PerformanceMeasure";
|
||||
|
||||
[_detail] = null;
|
||||
|
||||
get detail() {
|
||||
|
@ -552,10 +547,6 @@
|
|||
keys: [],
|
||||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Performance";
|
||||
}
|
||||
}
|
||||
webidl.configurePrototype(Performance);
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolIterator,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
|
@ -291,10 +290,6 @@
|
|||
webidl.assertBranded(this, URLSearchParams);
|
||||
return core.opSync("op_url_stringify_search_params", this[_list]);
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "URLSearchParams";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.mixinPairIterable("URLSearchParams", URLSearchParams, _list, 0, 1);
|
||||
|
@ -596,10 +591,6 @@
|
|||
webidl.assertBranded(this, URL);
|
||||
return this[_url].href;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "URL";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(URL);
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
ObjectEntries,
|
||||
ObjectSetPrototypeOf,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
} = window.__bootstrap.primordials;
|
||||
const webidl = window.__bootstrap.webidl;
|
||||
const consoleInternal = window.__bootstrap.console;
|
||||
|
@ -120,10 +119,6 @@
|
|||
return this.#code;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "DOMException";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
if (this instanceof DOMException) {
|
||||
return `DOMException: ${this.#message}`;
|
||||
|
|
|
@ -395,6 +395,9 @@
|
|||
get timeStamp() {
|
||||
return this[_attributes].timeStamp;
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): remove when this interface is spec aligned
|
||||
[SymbolToStringTag] = "Event";
|
||||
}
|
||||
|
||||
function defineEnumerableProps(
|
||||
|
@ -988,15 +991,13 @@
|
|||
return dispatch(self, event);
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "EventTarget";
|
||||
}
|
||||
|
||||
getParent(_event) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(EventTarget);
|
||||
|
||||
defineEnumerableProps(EventTarget, [
|
||||
"addEventListener",
|
||||
"removeEventListener",
|
||||
|
@ -1052,10 +1053,6 @@
|
|||
this.#error = error;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ErrorEvent";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.privateCustomInspect")](inspect) {
|
||||
return inspect(consoleInternal.createFilteredInspectProxy({
|
||||
object: this,
|
||||
|
@ -1070,6 +1067,9 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): remove when this interface is spec aligned
|
||||
[SymbolToStringTag] = "ErrorEvent";
|
||||
}
|
||||
|
||||
defineEnumerableProps(ErrorEvent, [
|
||||
|
@ -1158,6 +1158,9 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): remove when this interface is spec aligned
|
||||
[SymbolToStringTag] = "CloseEvent";
|
||||
}
|
||||
|
||||
class CustomEvent extends Event {
|
||||
|
@ -1176,10 +1179,6 @@
|
|||
return this.#detail;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "CustomEvent";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.privateCustomInspect")](inspect) {
|
||||
return inspect(consoleInternal.createFilteredInspectProxy({
|
||||
object: this,
|
||||
|
@ -1190,6 +1189,9 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): remove when this interface is spec aligned
|
||||
[SymbolToStringTag] = "CustomEvent";
|
||||
}
|
||||
|
||||
ReflectDefineProperty(CustomEvent.prototype, "detail", {
|
||||
|
@ -1219,6 +1221,9 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): remove when this interface is spec aligned
|
||||
[SymbolToStringTag] = "ProgressEvent";
|
||||
}
|
||||
|
||||
const _eventHandlers = Symbol("eventHandlers");
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
SetPrototypeAdd,
|
||||
SetPrototypeDelete,
|
||||
Symbol,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
|
@ -72,10 +71,6 @@
|
|||
get aborted() {
|
||||
return Boolean(this[aborted]);
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "AbortSignal";
|
||||
}
|
||||
}
|
||||
defineEventHandler(AbortSignal.prototype, "abort");
|
||||
|
||||
|
@ -91,10 +86,6 @@
|
|||
abort() {
|
||||
this.#signal[signalAbort]();
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "AbortController";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(AbortController);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
Symbol,
|
||||
SymbolAsyncIterator,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
Uint8Array,
|
||||
WeakMap,
|
||||
|
@ -3031,10 +3030,6 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ByteLengthQueuingStrategy";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(ByteLengthQueuingStrategy);
|
||||
|
@ -3087,10 +3082,6 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "CountQueuingStrategy";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(CountQueuingStrategy);
|
||||
|
@ -3339,10 +3330,6 @@
|
|||
[SymbolFor("Deno.privateCustomInspect")](inspect) {
|
||||
return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ReadableStream";
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(lucacasonato): should be moved to webidl crate
|
||||
|
@ -3459,10 +3446,6 @@
|
|||
[SymbolFor("Deno.privateCustomInspect")](inspect) {
|
||||
return `${this.constructor.name} ${inspect({ closed: this.closed })}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ReadableStreamDefaultReader";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(ReadableStreamDefaultReader);
|
||||
|
@ -3582,10 +3565,6 @@
|
|||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ReadableByteStreamController";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} reason
|
||||
* @returns {Promise<void>}
|
||||
|
@ -3707,10 +3686,6 @@
|
|||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "ReadableStreamDefaultController";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any} reason
|
||||
* @returns {Promise<void>}
|
||||
|
@ -3861,10 +3836,6 @@
|
|||
inspect({ readable: this.readable, writable: this.writable })
|
||||
}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TransformStream";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TransformStream);
|
||||
|
@ -3928,10 +3899,6 @@
|
|||
keys: ["desiredSize"],
|
||||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TransformStreamDefaultController";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TransformStreamDefaultController);
|
||||
|
@ -4062,10 +4029,6 @@
|
|||
[SymbolFor("Deno.privateCustomInspect")](inspect) {
|
||||
return `${this.constructor.name} ${inspect({ locked: this.locked })}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "WritableStream";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(WritableStream);
|
||||
|
@ -4211,10 +4174,6 @@
|
|||
],
|
||||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "WritableStreamDefaultWriter";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(WritableStreamDefaultWriter);
|
||||
|
@ -4268,10 +4227,6 @@
|
|||
}));
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "WritableStreamDefaultController";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any=} reason
|
||||
* @returns {Promise<void>}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
PromiseResolve,
|
||||
StringPrototypeCharCodeAt,
|
||||
StringPrototypeSlice,
|
||||
SymbolToStringTag,
|
||||
TypedArrayPrototypeSubarray,
|
||||
TypedArrayPrototypeSlice,
|
||||
Uint8Array,
|
||||
|
@ -126,10 +125,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TextDecoder";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TextDecoder);
|
||||
|
@ -182,10 +177,6 @@
|
|||
});
|
||||
return core.opSync("op_encoding_encode_into", source, destination);
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TextEncoder";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TextEncoder);
|
||||
|
@ -272,10 +263,6 @@
|
|||
webidl.assertBranded(this, TextDecoderStream);
|
||||
return this.#transform.writable;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TextDecoderStream";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TextDecoderStream);
|
||||
|
@ -345,10 +332,6 @@
|
|||
webidl.assertBranded(this, TextEncoderStream);
|
||||
return this.#transform.writable;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "TextEncoderStream";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(TextEncoderStream);
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
Symbol,
|
||||
SymbolFor,
|
||||
TypedArrayPrototypeSet,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
Uint8Array,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
@ -359,10 +358,6 @@
|
|||
return bytes.buffer;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "Blob";
|
||||
}
|
||||
|
||||
[SymbolFor("Deno.customInspect")](inspect) {
|
||||
return inspect(consoleInternal.createFilteredInspectProxy({
|
||||
object: this,
|
||||
|
@ -472,10 +467,6 @@
|
|||
webidl.assertBranded(this, File);
|
||||
return this[_LastModified];
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "File";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(File);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
queueMicrotask,
|
||||
StringFromCodePoint,
|
||||
Symbol,
|
||||
SymbolToStringTag,
|
||||
TypedArrayPrototypeSet,
|
||||
TypeError,
|
||||
Uint8Array,
|
||||
|
@ -44,10 +43,6 @@
|
|||
const handlerSymbol = Symbol("eventHandlers");
|
||||
|
||||
class FileReader extends EventTarget {
|
||||
get [SymbolToStringTag]() {
|
||||
return "FileReader";
|
||||
}
|
||||
|
||||
/** @type {"empty" | "loading" | "done"} */
|
||||
[state] = "empty";
|
||||
/** @type {null | string | ArrayBuffer} */
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
ObjectSetPrototypeOf,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
SymbolToStringTag,
|
||||
TypeError,
|
||||
WeakSet,
|
||||
WeakSetPrototypeAdd,
|
||||
|
@ -59,10 +58,6 @@
|
|||
inspect({ port1: this.port1, port2: this.port2 })
|
||||
}`;
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "MessageChannel";
|
||||
}
|
||||
}
|
||||
|
||||
webidl.configurePrototype(MessageChannel);
|
||||
|
@ -174,10 +169,6 @@
|
|||
this[_id] = null;
|
||||
}
|
||||
}
|
||||
|
||||
get [SymbolToStringTag]() {
|
||||
return "MessagePort";
|
||||
}
|
||||
}
|
||||
|
||||
defineEventHandler(MessagePort.prototype, "message", function (self) {
|
||||
|
|
|
@ -1053,6 +1053,12 @@
|
|||
});
|
||||
}
|
||||
}
|
||||
ObjectDefineProperty(prototype.prototype, SymbolToStringTag, {
|
||||
value: prototype.name,
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: false,
|
||||
});
|
||||
}
|
||||
|
||||
window.__bootstrap ??= {};
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
StringPrototypeStartsWith,
|
||||
String,
|
||||
SymbolIterator,
|
||||
SymbolToStringTag,
|
||||
} = window.__bootstrap.primordials;
|
||||
const webidl = window.__bootstrap.webidl;
|
||||
const { URL } = window.__bootstrap.url;
|
||||
|
@ -351,6 +352,8 @@
|
|||
hostTerminateWorker(this.#id);
|
||||
}
|
||||
}
|
||||
|
||||
[SymbolToStringTag] = "Worker";
|
||||
}
|
||||
|
||||
defineEventHandler(Worker.prototype, "error");
|
||||
|
|
|
@ -12150,16 +12150,7 @@
|
|||
},
|
||||
"historical.any.html": false,
|
||||
"idlharness.https.any.html": [
|
||||
"SubtleCrypto interface: operation encrypt(AlgorithmIdentifier, CryptoKey, BufferSource)",
|
||||
"SubtleCrypto interface: operation decrypt(AlgorithmIdentifier, CryptoKey, BufferSource)",
|
||||
"SubtleCrypto interface: operation sign(AlgorithmIdentifier, CryptoKey, BufferSource)",
|
||||
"SubtleCrypto interface: operation verify(AlgorithmIdentifier, CryptoKey, BufferSource, BufferSource)",
|
||||
"SubtleCrypto interface: operation digest(AlgorithmIdentifier, BufferSource)",
|
||||
"SubtleCrypto interface: operation generateKey(AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||
"SubtleCrypto interface: operation deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||
"SubtleCrypto interface: operation deriveBits(AlgorithmIdentifier, CryptoKey, unsigned long)",
|
||||
"SubtleCrypto interface: operation importKey(KeyFormat, (BufferSource or JsonWebKey), AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||
"SubtleCrypto interface: operation exportKey(KeyFormat, CryptoKey)",
|
||||
"SubtleCrypto interface: operation wrapKey(KeyFormat, CryptoKey, CryptoKey, AlgorithmIdentifier)",
|
||||
"SubtleCrypto interface: operation unwrapKey(KeyFormat, BufferSource, CryptoKey, AlgorithmIdentifier, AlgorithmIdentifier, boolean, sequence<KeyUsage>)",
|
||||
"SubtleCrypto interface: crypto.subtle must inherit property \"deriveKey(AlgorithmIdentifier, CryptoKey, AlgorithmIdentifier, boolean, sequence<KeyUsage>)\" with the proper type",
|
||||
|
@ -13572,9 +13563,7 @@
|
|||
"If the implementation has a stack property on normal errors, it also does on DOMExceptions"
|
||||
]
|
||||
},
|
||||
"class-string-interface.any.html": [
|
||||
"@@toStringTag exists on the prototype with the appropriate descriptor"
|
||||
],
|
||||
"class-string-interface.any.html": true,
|
||||
"class-string-iterator-prototype-object.any.html": true,
|
||||
"global-immutable-prototype.any.html": [
|
||||
"Setting to a different prototype"
|
||||
|
@ -14573,4 +14562,4 @@
|
|||
"Pattern: [{\"pathname\":\"/foo/bar\"}] Inputs: [\"./foo/bar\",\"https://example.com\"]"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue