feat: refactoring project
This commit is contained in:
5
node_modules/webpack/lib/sharing/ConsumeSharedModule.js
generated
vendored
5
node_modules/webpack/lib/sharing/ConsumeSharedModule.js
generated
vendored
@@ -8,6 +8,7 @@
|
||||
const { RawSource } = require("webpack-sources");
|
||||
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
|
||||
const Module = require("../Module");
|
||||
const { CONSUME_SHARED_TYPES } = require("../ModuleSourceTypesConstants");
|
||||
const {
|
||||
WEBPACK_MODULE_TYPE_CONSUME_SHARED_MODULE
|
||||
} = require("../ModuleTypeConstants");
|
||||
@@ -48,8 +49,6 @@ const ConsumeSharedFallbackDependency = require("./ConsumeSharedFallbackDependen
|
||||
* @property {boolean} eager include the fallback module in a sync way
|
||||
*/
|
||||
|
||||
const TYPES = new Set(["consume-shared"]);
|
||||
|
||||
class ConsumeSharedModule extends Module {
|
||||
/**
|
||||
* @param {string} context context
|
||||
@@ -151,7 +150,7 @@ class ConsumeSharedModule extends Module {
|
||||
* @returns {SourceTypes} types available (do not mutate)
|
||||
*/
|
||||
getSourceTypes() {
|
||||
return TYPES;
|
||||
return CONSUME_SHARED_TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
221
node_modules/webpack/lib/sharing/ConsumeSharedPlugin.js
generated
vendored
221
node_modules/webpack/lib/sharing/ConsumeSharedPlugin.js
generated
vendored
@@ -27,7 +27,9 @@ const {
|
||||
/** @typedef {import("../../declarations/plugins/sharing/ConsumeSharedPlugin").ConsumesConfig} ConsumesConfig */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../ResolverFactory").ResolveOptionsWithDependencyType} ResolveOptionsWithDependencyType */
|
||||
/** @typedef {import("../util/semver").SemVerRange} SemVerRange */
|
||||
/** @typedef {import("./ConsumeSharedModule").ConsumeOptions} ConsumeOptions */
|
||||
/** @typedef {import("./utils").DescriptionFile} DescriptionFile */
|
||||
|
||||
const validate = createSchemaValidation(
|
||||
require("../../schemas/plugins/sharing/ConsumeSharedPlugin.check.js"),
|
||||
@@ -57,7 +59,7 @@ class ConsumeSharedPlugin {
|
||||
(item, key) => {
|
||||
if (Array.isArray(item)) throw new Error("Unexpected array in options");
|
||||
/** @type {ConsumeOptions} */
|
||||
let result =
|
||||
const result =
|
||||
item === key || !isRequiredVersion(item)
|
||||
? // item is a request/key
|
||||
{
|
||||
@@ -97,8 +99,8 @@ class ConsumeSharedPlugin {
|
||||
? item.strictVersion
|
||||
: item.import !== false && !item.singleton,
|
||||
packageName: item.packageName,
|
||||
singleton: !!item.singleton,
|
||||
eager: !!item.eager
|
||||
singleton: Boolean(item.singleton),
|
||||
eager: Boolean(item.eager)
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -157,110 +159,127 @@ class ConsumeSharedPlugin {
|
||||
config.import &&
|
||||
/^(\.\.?(\/|$)|\/|[A-Za-z]:|\\\\)/.test(config.import);
|
||||
return Promise.all([
|
||||
new Promise(resolve => {
|
||||
if (!config.import) return resolve();
|
||||
const resolveContext = {
|
||||
/** @type {LazySet<string>} */
|
||||
fileDependencies: new LazySet(),
|
||||
/** @type {LazySet<string>} */
|
||||
contextDependencies: new LazySet(),
|
||||
/** @type {LazySet<string>} */
|
||||
missingDependencies: new LazySet()
|
||||
};
|
||||
resolver.resolve(
|
||||
{},
|
||||
directFallback ? compiler.context : context,
|
||||
config.import,
|
||||
resolveContext,
|
||||
(err, result) => {
|
||||
compilation.contextDependencies.addAll(
|
||||
resolveContext.contextDependencies
|
||||
);
|
||||
compilation.fileDependencies.addAll(
|
||||
resolveContext.fileDependencies
|
||||
);
|
||||
compilation.missingDependencies.addAll(
|
||||
resolveContext.missingDependencies
|
||||
);
|
||||
if (err) {
|
||||
compilation.errors.push(
|
||||
new ModuleNotFoundError(null, err, {
|
||||
name: `resolving fallback for shared module ${request}`
|
||||
})
|
||||
new Promise(
|
||||
/**
|
||||
* @param {(value?: string) => void} resolve resolve
|
||||
*/
|
||||
resolve => {
|
||||
if (!config.import) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const resolveContext = {
|
||||
/** @type {LazySet<string>} */
|
||||
fileDependencies: new LazySet(),
|
||||
/** @type {LazySet<string>} */
|
||||
contextDependencies: new LazySet(),
|
||||
/** @type {LazySet<string>} */
|
||||
missingDependencies: new LazySet()
|
||||
};
|
||||
resolver.resolve(
|
||||
{},
|
||||
directFallback ? compiler.context : context,
|
||||
config.import,
|
||||
resolveContext,
|
||||
(err, result) => {
|
||||
compilation.contextDependencies.addAll(
|
||||
resolveContext.contextDependencies
|
||||
);
|
||||
return resolve();
|
||||
compilation.fileDependencies.addAll(
|
||||
resolveContext.fileDependencies
|
||||
);
|
||||
compilation.missingDependencies.addAll(
|
||||
resolveContext.missingDependencies
|
||||
);
|
||||
if (err) {
|
||||
compilation.errors.push(
|
||||
new ModuleNotFoundError(null, err, {
|
||||
name: `resolving fallback for shared module ${request}`
|
||||
})
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
resolve(/** @type {string} */ (result));
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
);
|
||||
}),
|
||||
new Promise(resolve => {
|
||||
if (config.requiredVersion !== undefined)
|
||||
return resolve(config.requiredVersion);
|
||||
let packageName = config.packageName;
|
||||
if (packageName === undefined) {
|
||||
if (/^(\/|[A-Za-z]:|\\\\)/.test(request)) {
|
||||
// For relative or absolute requests we don't automatically use a packageName.
|
||||
// If wished one can specify one with the packageName option.
|
||||
return resolve();
|
||||
}
|
||||
const match = /^((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(request);
|
||||
if (!match) {
|
||||
requiredVersionWarning(
|
||||
"Unable to extract the package name from request."
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
packageName = match[0];
|
||||
);
|
||||
}
|
||||
),
|
||||
new Promise(
|
||||
/**
|
||||
* @param {(value?: SemVerRange) => void} resolve resolve
|
||||
*/
|
||||
resolve => {
|
||||
if (config.requiredVersion !== undefined) {
|
||||
resolve(/** @type {SemVerRange} */ (config.requiredVersion));
|
||||
return;
|
||||
}
|
||||
let packageName = config.packageName;
|
||||
if (packageName === undefined) {
|
||||
if (/^(\/|[A-Za-z]:|\\\\)/.test(request)) {
|
||||
// For relative or absolute requests we don't automatically use a packageName.
|
||||
// If wished one can specify one with the packageName option.
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const match = /^((?:@[^\\/]+[\\/])?[^\\/]+)/.exec(request);
|
||||
if (!match) {
|
||||
requiredVersionWarning(
|
||||
"Unable to extract the package name from request."
|
||||
);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
packageName = match[0];
|
||||
}
|
||||
|
||||
getDescriptionFile(
|
||||
compilation.inputFileSystem,
|
||||
context,
|
||||
["package.json"],
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
requiredVersionWarning(
|
||||
`Unable to read description file: ${err}`
|
||||
);
|
||||
return resolve();
|
||||
getDescriptionFile(
|
||||
compilation.inputFileSystem,
|
||||
context,
|
||||
["package.json"],
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
requiredVersionWarning(
|
||||
`Unable to read description file: ${err}`
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
const { data, path: descriptionPath } =
|
||||
/** @type {DescriptionFile} */ (result);
|
||||
if (!data) {
|
||||
requiredVersionWarning(
|
||||
`Unable to find description file in ${context}.`
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
if (data.name === packageName) {
|
||||
// Package self-referencing
|
||||
return resolve();
|
||||
}
|
||||
const requiredVersion =
|
||||
getRequiredVersionFromDescriptionFile(data, packageName);
|
||||
if (typeof requiredVersion !== "string") {
|
||||
requiredVersionWarning(
|
||||
`Unable to find required version for "${packageName}" in description file (${descriptionPath}). It need to be in dependencies, devDependencies or peerDependencies.`
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
resolve(parseRange(requiredVersion));
|
||||
}
|
||||
const { data, path: descriptionPath } = result;
|
||||
if (!data) {
|
||||
requiredVersionWarning(
|
||||
`Unable to find description file in ${context}.`
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
if (data.name === packageName) {
|
||||
// Package self-referencing
|
||||
return resolve();
|
||||
}
|
||||
const requiredVersion = getRequiredVersionFromDescriptionFile(
|
||||
data,
|
||||
packageName
|
||||
);
|
||||
if (typeof requiredVersion !== "string") {
|
||||
requiredVersionWarning(
|
||||
`Unable to find required version for "${packageName}" in description file (${descriptionPath}). It need to be in dependencies, devDependencies or peerDependencies.`
|
||||
);
|
||||
return resolve();
|
||||
}
|
||||
resolve(parseRange(requiredVersion));
|
||||
}
|
||||
);
|
||||
})
|
||||
]).then(([importResolved, requiredVersion]) => {
|
||||
return new ConsumeSharedModule(
|
||||
directFallback ? compiler.context : context,
|
||||
{
|
||||
...config,
|
||||
importResolved,
|
||||
import: importResolved ? config.import : undefined,
|
||||
requiredVersion
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
)
|
||||
]).then(
|
||||
([importResolved, requiredVersion]) =>
|
||||
new ConsumeSharedModule(
|
||||
directFallback ? compiler.context : context,
|
||||
{
|
||||
...config,
|
||||
importResolved,
|
||||
import: importResolved ? config.import : undefined,
|
||||
requiredVersion
|
||||
}
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
normalModuleFactory.hooks.factorize.tapPromise(
|
||||
|
||||
12
node_modules/webpack/lib/sharing/ConsumeSharedRuntimeModule.js
generated
vendored
12
node_modules/webpack/lib/sharing/ConsumeSharedRuntimeModule.js
generated
vendored
@@ -19,6 +19,7 @@ const {
|
||||
/** @typedef {import("../Chunk")} Chunk */
|
||||
/** @typedef {import("../Chunk").ChunkId} ChunkId */
|
||||
/** @typedef {import("../ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
/** @typedef {import("../Module").ReadOnlyRuntimeRequirements} ReadOnlyRuntimeRequirements */
|
||||
@@ -47,15 +48,14 @@ class ConsumeSharedRuntimeModule extends RuntimeModule {
|
||||
/** @type {(string | number)[]} */
|
||||
const initialConsumes = [];
|
||||
/**
|
||||
*
|
||||
* @param {Iterable<Module>} modules modules
|
||||
* @param {Chunk} chunk the chunk
|
||||
* @param {(string | number)[]} list list of ids
|
||||
*/
|
||||
const addModules = (modules, chunk, list) => {
|
||||
for (const m of modules) {
|
||||
const module = /** @type {ConsumeSharedModule} */ (m);
|
||||
const id = chunkGraph.getModuleId(module);
|
||||
const module = m;
|
||||
const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
|
||||
list.push(id);
|
||||
moduleIdToSourceMapping.set(
|
||||
id,
|
||||
@@ -67,7 +67,9 @@ class ConsumeSharedRuntimeModule extends RuntimeModule {
|
||||
);
|
||||
}
|
||||
};
|
||||
for (const chunk of /** @type {Chunk} */ (this.chunk).getAllAsyncChunks()) {
|
||||
for (const chunk of /** @type {Chunk} */ (
|
||||
this.chunk
|
||||
).getAllReferencedChunks()) {
|
||||
const modules = chunkGraph.getChunkModulesIterableBySourceType(
|
||||
chunk,
|
||||
"consume-shared"
|
||||
@@ -283,7 +285,7 @@ class ConsumeSharedRuntimeModule extends RuntimeModule {
|
||||
`delete ${RuntimeGlobals.moduleCache}[id];`,
|
||||
"var factory = moduleToHandlerMapping[id]();",
|
||||
'if(typeof factory !== "function") throw new Error("Shared module is not available for eager consumption: " + id);',
|
||||
`module.exports = factory();`
|
||||
"module.exports = factory();"
|
||||
])}`
|
||||
])});`
|
||||
])
|
||||
|
||||
1
node_modules/webpack/lib/sharing/ProvideForSharedDependency.js
generated
vendored
1
node_modules/webpack/lib/sharing/ProvideForSharedDependency.js
generated
vendored
@@ -10,7 +10,6 @@ const makeSerializable = require("../util/makeSerializable");
|
||||
|
||||
class ProvideForSharedDependency extends ModuleDependency {
|
||||
/**
|
||||
*
|
||||
* @param {string} request request string
|
||||
*/
|
||||
constructor(request) {
|
||||
|
||||
5
node_modules/webpack/lib/sharing/ProvideSharedModule.js
generated
vendored
5
node_modules/webpack/lib/sharing/ProvideSharedModule.js
generated
vendored
@@ -7,6 +7,7 @@
|
||||
|
||||
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
|
||||
const Module = require("../Module");
|
||||
const { SHARED_INIT_TYPES } = require("../ModuleSourceTypesConstants");
|
||||
const { WEBPACK_MODULE_TYPE_PROVIDE } = require("../ModuleTypeConstants");
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const makeSerializable = require("../util/makeSerializable");
|
||||
@@ -30,8 +31,6 @@ const ProvideForSharedDependency = require("./ProvideForSharedDependency");
|
||||
/** @typedef {import("../util/Hash")} Hash */
|
||||
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
|
||||
|
||||
const TYPES = new Set(["share-init"]);
|
||||
|
||||
class ProvideSharedModule extends Module {
|
||||
/**
|
||||
* @param {string} shareScope shared scope name
|
||||
@@ -124,7 +123,7 @@ class ProvideSharedModule extends Module {
|
||||
* @returns {SourceTypes} types available (do not mutate)
|
||||
*/
|
||||
getSourceTypes() {
|
||||
return TYPES;
|
||||
return SHARED_INIT_TYPES;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
4
node_modules/webpack/lib/sharing/ProvideSharedPlugin.js
generated
vendored
4
node_modules/webpack/lib/sharing/ProvideSharedPlugin.js
generated
vendored
@@ -62,7 +62,7 @@ class ProvideSharedPlugin {
|
||||
shareKey: item.shareKey,
|
||||
version: item.version,
|
||||
shareScope: item.shareScope || options.shareScope || "default",
|
||||
eager: !!item.eager
|
||||
eager: Boolean(item.eager)
|
||||
})
|
||||
)
|
||||
);
|
||||
@@ -129,7 +129,7 @@ class ProvideSharedPlugin {
|
||||
if (version === undefined) {
|
||||
let details = "";
|
||||
if (!resourceResolveData) {
|
||||
details = `No resolve data provided from resolver.`;
|
||||
details = "No resolve data provided from resolver.";
|
||||
} else {
|
||||
const descriptionFileData =
|
||||
resourceResolveData.descriptionFileData;
|
||||
|
||||
3
node_modules/webpack/lib/sharing/resolveMatchedConfigs.js
generated
vendored
3
node_modules/webpack/lib/sharing/resolveMatchedConfigs.js
generated
vendored
@@ -28,7 +28,7 @@ const RESOLVE_OPTIONS = { dependencyType: "esm" };
|
||||
* @param {[string, T][]} configs to be processed configs
|
||||
* @returns {Promise<MatchedConfigs<T>>} resolved matchers
|
||||
*/
|
||||
exports.resolveMatchedConfigs = (compilation, configs) => {
|
||||
module.exports.resolveMatchedConfigs = (compilation, configs) => {
|
||||
/** @type {Map<string, T>} */
|
||||
const resolved = new Map();
|
||||
/** @type {Map<string, T>} */
|
||||
@@ -47,6 +47,7 @@ exports.resolveMatchedConfigs = (compilation, configs) => {
|
||||
const context = compilation.compiler.context;
|
||||
|
||||
return Promise.all(
|
||||
// eslint-disable-next-line array-callback-return
|
||||
configs.map(([request, config]) => {
|
||||
if (/^\.\.?(\/|$)/.test(request)) {
|
||||
// relative request
|
||||
|
||||
42
node_modules/webpack/lib/sharing/utils.js
generated
vendored
42
node_modules/webpack/lib/sharing/utils.js
generated
vendored
@@ -65,11 +65,7 @@ const extractCommithashByDomain = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
commithash = hash;
|
||||
} else {
|
||||
commithash = "#" + commithash;
|
||||
}
|
||||
commithash = !type ? hash : `#${commithash}`;
|
||||
|
||||
if (project && project.endsWith(".git")) {
|
||||
project = project.slice(0, -4);
|
||||
@@ -155,7 +151,6 @@ const extractCommithashByDomain = {
|
||||
|
||||
/**
|
||||
* extract commit hash from parsed url
|
||||
*
|
||||
* @inner
|
||||
* @param {URL} urlParsed parsed url
|
||||
* @returns {string} commithash
|
||||
@@ -167,7 +162,7 @@ function getCommithash(urlParsed) {
|
||||
try {
|
||||
hash = decodeURIComponent(hash);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
} catch (_err) {}
|
||||
|
||||
if (
|
||||
extractCommithashByDomain[
|
||||
@@ -186,7 +181,6 @@ function getCommithash(urlParsed) {
|
||||
|
||||
/**
|
||||
* make url right for URL parse
|
||||
*
|
||||
* @inner
|
||||
* @param {string} gitUrl git url
|
||||
* @returns {string} fixed url
|
||||
@@ -199,7 +193,6 @@ function correctUrl(gitUrl) {
|
||||
|
||||
/**
|
||||
* make url protocol right for URL parse
|
||||
*
|
||||
* @inner
|
||||
* @param {string} gitUrl git url
|
||||
* @returns {string} fixed url
|
||||
@@ -220,7 +213,6 @@ function correctProtocol(gitUrl) {
|
||||
|
||||
/**
|
||||
* extract git dep version from hash
|
||||
*
|
||||
* @inner
|
||||
* @param {string} hash hash
|
||||
* @returns {string} git dep version
|
||||
@@ -233,7 +225,6 @@ function getVersionFromHash(hash) {
|
||||
|
||||
/**
|
||||
* if string can be decoded
|
||||
*
|
||||
* @inner
|
||||
* @param {string} str str to be checked
|
||||
* @returns {boolean} if can be decoded
|
||||
@@ -241,7 +232,7 @@ function getVersionFromHash(hash) {
|
||||
function canBeDecoded(str) {
|
||||
try {
|
||||
decodeURIComponent(str);
|
||||
} catch (e) {
|
||||
} catch (_err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -250,19 +241,16 @@ function canBeDecoded(str) {
|
||||
|
||||
/**
|
||||
* get right dep version from git url
|
||||
*
|
||||
* @inner
|
||||
* @param {string} gitUrl git url
|
||||
* @returns {string} dep version
|
||||
*/
|
||||
function getGitUrlVersion(gitUrl) {
|
||||
let oriGitUrl = gitUrl;
|
||||
const oriGitUrl = gitUrl;
|
||||
// github extreme shorthand
|
||||
if (RE_URL_GITHUB_EXTREME_SHORT.test(gitUrl)) {
|
||||
gitUrl = "github:" + gitUrl;
|
||||
} else {
|
||||
gitUrl = correctProtocol(gitUrl);
|
||||
}
|
||||
gitUrl = RE_URL_GITHUB_EXTREME_SHORT.test(gitUrl)
|
||||
? `github:${gitUrl}`
|
||||
: correctProtocol(gitUrl);
|
||||
|
||||
gitUrl = correctUrl(gitUrl);
|
||||
|
||||
@@ -270,7 +258,7 @@ function getGitUrlVersion(gitUrl) {
|
||||
try {
|
||||
parsed = new URL(gitUrl);
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (e) {}
|
||||
} catch (_err) {}
|
||||
|
||||
if (!parsed) {
|
||||
return "";
|
||||
@@ -312,7 +300,7 @@ function isRequiredVersion(str) {
|
||||
return VERSION_PATTERN_REGEXP.test(str);
|
||||
}
|
||||
|
||||
exports.isRequiredVersion = isRequiredVersion;
|
||||
module.exports.isRequiredVersion = isRequiredVersion;
|
||||
|
||||
/**
|
||||
* @see https://docs.npmjs.com/cli/v7/configuring-npm/package-json#urls-as-dependencies
|
||||
@@ -330,14 +318,15 @@ function normalizeVersion(versionDesc) {
|
||||
return getGitUrlVersion(versionDesc.toLowerCase());
|
||||
}
|
||||
|
||||
exports.normalizeVersion = normalizeVersion;
|
||||
module.exports.normalizeVersion = normalizeVersion;
|
||||
|
||||
/** @typedef {{ data: JsonObject, path: string }} DescriptionFile */
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {InputFileSystem} fs file system
|
||||
* @param {string} directory directory to start looking into
|
||||
* @param {string[]} descriptionFiles possible description filenames
|
||||
* @param {function((Error | null)=, {data: object, path: string}=): void} callback callback
|
||||
* @param {function((Error | null)=, DescriptionFile=): void} callback callback
|
||||
*/
|
||||
const getDescriptionFile = (fs, directory, descriptionFiles, callback) => {
|
||||
let i = 0;
|
||||
@@ -371,10 +360,9 @@ const getDescriptionFile = (fs, directory, descriptionFiles, callback) => {
|
||||
};
|
||||
tryLoadCurrent();
|
||||
};
|
||||
exports.getDescriptionFile = getDescriptionFile;
|
||||
module.exports.getDescriptionFile = getDescriptionFile;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {JsonObject} data description file data i.e.: package.json
|
||||
* @param {string} packageName name of the dependency
|
||||
* @returns {string | undefined} normalized version
|
||||
@@ -402,5 +390,5 @@ const getRequiredVersionFromDescriptionFile = (data, packageName) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.getRequiredVersionFromDescriptionFile =
|
||||
module.exports.getRequiredVersionFromDescriptionFile =
|
||||
getRequiredVersionFromDescriptionFile;
|
||||
|
||||
Reference in New Issue
Block a user