UNPKG

28.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Manifest = void 0;
4const tslib_1 = require("tslib");
5const fslib_1 = require("@yarnpkg/fslib");
6const parsers_1 = require("@yarnpkg/parsers");
7const semver_1 = tslib_1.__importDefault(require("semver"));
8const miscUtils = tslib_1.__importStar(require("./miscUtils"));
9const semverUtils = tslib_1.__importStar(require("./semverUtils"));
10const structUtils = tslib_1.__importStar(require("./structUtils"));
11class Manifest {
12 constructor() {
13 this.indent = ` `;
14 this.name = null;
15 this.version = null;
16 this.os = null;
17 this.cpu = null;
18 this.type = null;
19 this["private"] = false;
20 this.license = null;
21 this.main = null;
22 this.module = null;
23 this.browser = null;
24 this.languageName = null;
25 this.bin = new Map();
26 this.scripts = new Map();
27 this.dependencies = new Map();
28 this.devDependencies = new Map();
29 this.peerDependencies = new Map();
30 this.workspaceDefinitions = [];
31 this.dependenciesMeta = new Map();
32 this.peerDependenciesMeta = new Map();
33 this.resolutions = [];
34 this.files = null;
35 this.publishConfig = null;
36 this.installConfig = null;
37 this.preferUnplugged = null;
38 this.raw = {};
39 /**
40 * errors found in the raw manifest while loading
41 */
42 this.errors = [];
43 }
44 static async tryFind(path, { baseFs = new fslib_1.NodeFS() } = {}) {
45 const manifestPath = fslib_1.ppath.join(path, `package.json`);
46 if (!await baseFs.existsPromise(manifestPath))
47 return null;
48 return await Manifest.fromFile(manifestPath, { baseFs });
49 }
50 static async find(path, { baseFs } = {}) {
51 const manifest = await Manifest.tryFind(path, { baseFs });
52 if (manifest === null)
53 throw new Error(`Manifest not found`);
54 return manifest;
55 }
56 static async fromFile(path, { baseFs = new fslib_1.NodeFS() } = {}) {
57 const manifest = new Manifest();
58 await manifest.loadFile(path, { baseFs });
59 return manifest;
60 }
61 static fromText(text) {
62 const manifest = new Manifest();
63 manifest.loadFromText(text);
64 return manifest;
65 }
66 loadFromText(text) {
67 let data;
68 try {
69 data = JSON.parse(stripBOM(text) || `{}`);
70 }
71 catch (error) {
72 error.message += ` (when parsing ${text})`;
73 throw error;
74 }
75 this.load(data);
76 this.indent = getIndent(text);
77 }
78 async loadFile(path, { baseFs = new fslib_1.NodeFS() }) {
79 const content = await baseFs.readFilePromise(path, `utf8`);
80 let data;
81 try {
82 data = JSON.parse(stripBOM(content) || `{}`);
83 }
84 catch (error) {
85 error.message += ` (when parsing ${path})`;
86 throw error;
87 }
88 this.load(data);
89 this.indent = getIndent(content);
90 }
91 load(data) {
92 if (typeof data !== `object` || data === null)
93 throw new Error(`Utterly invalid manifest data (${data})`);
94 this.raw = data;
95 const errors = [];
96 if (typeof data.name === `string`) {
97 try {
98 this.name = structUtils.parseIdent(data.name);
99 }
100 catch (error) {
101 errors.push(new Error(`Parsing failed for the 'name' field`));
102 }
103 }
104 if (typeof data.version === `string`)
105 this.version = data.version;
106 if (Array.isArray(data.os)) {
107 const os = [];
108 this.os = os;
109 for (const item of data.os) {
110 if (typeof item !== `string`) {
111 errors.push(new Error(`Parsing failed for the 'os' field`));
112 }
113 else {
114 os.push(item);
115 }
116 }
117 }
118 if (Array.isArray(data.cpu)) {
119 const cpu = [];
120 this.cpu = cpu;
121 for (const item of data.cpu) {
122 if (typeof item !== `string`) {
123 errors.push(new Error(`Parsing failed for the 'cpu' field`));
124 }
125 else {
126 cpu.push(item);
127 }
128 }
129 }
130 if (typeof data.type === `string`)
131 this.type = data.type;
132 if (typeof data.private === `boolean`)
133 this.private = data.private;
134 if (typeof data.license === `string`)
135 this.license = data.license;
136 if (typeof data.languageName === `string`)
137 this.languageName = data.languageName;
138 if (typeof data.main === `string`)
139 this.main = data.main;
140 if (typeof data.module === `string`)
141 this.module = data.module;
142 if (data.browser != null) {
143 if (typeof data.browser === `string`) {
144 this.browser = data.browser;
145 }
146 else {
147 this.browser = new Map(Object.entries(data.browser));
148 }
149 }
150 if (typeof data.bin === `string`) {
151 if (this.name !== null) {
152 this.bin = new Map([[this.name.name, data.bin]]);
153 }
154 else {
155 errors.push(new Error(`String bin field, but no attached package name`));
156 }
157 }
158 else if (typeof data.bin === `object` && data.bin !== null) {
159 for (const [key, value] of Object.entries(data.bin)) {
160 if (typeof value !== `string`) {
161 errors.push(new Error(`Invalid bin definition for '${key}'`));
162 continue;
163 }
164 this.bin.set(key, value);
165 }
166 }
167 if (typeof data.scripts === `object` && data.scripts !== null) {
168 for (const [key, value] of Object.entries(data.scripts)) {
169 if (typeof value !== `string`) {
170 errors.push(new Error(`Invalid script definition for '${key}'`));
171 continue;
172 }
173 this.scripts.set(key, value);
174 }
175 }
176 if (typeof data.dependencies === `object` && data.dependencies !== null) {
177 for (const [name, range] of Object.entries(data.dependencies)) {
178 if (typeof range !== `string`) {
179 errors.push(new Error(`Invalid dependency range for '${name}'`));
180 continue;
181 }
182 let ident;
183 try {
184 ident = structUtils.parseIdent(name);
185 }
186 catch (error) {
187 errors.push(new Error(`Parsing failed for the dependency name '${name}'`));
188 continue;
189 }
190 const descriptor = structUtils.makeDescriptor(ident, range);
191 this.dependencies.set(descriptor.identHash, descriptor);
192 }
193 }
194 if (typeof data.devDependencies === `object` && data.devDependencies !== null) {
195 for (const [name, range] of Object.entries(data.devDependencies)) {
196 if (typeof range !== `string`) {
197 errors.push(new Error(`Invalid dependency range for '${name}'`));
198 continue;
199 }
200 let ident;
201 try {
202 ident = structUtils.parseIdent(name);
203 }
204 catch (error) {
205 errors.push(new Error(`Parsing failed for the dependency name '${name}'`));
206 continue;
207 }
208 const descriptor = structUtils.makeDescriptor(ident, range);
209 this.devDependencies.set(descriptor.identHash, descriptor);
210 }
211 }
212 if (typeof data.peerDependencies === `object` && data.peerDependencies !== null) {
213 for (let [name, range] of Object.entries(data.peerDependencies)) {
214 let ident;
215 try {
216 ident = structUtils.parseIdent(name);
217 }
218 catch (error) {
219 errors.push(new Error(`Parsing failed for the dependency name '${name}'`));
220 continue;
221 }
222 if (typeof range !== `string` || !semverUtils.validRange(range)) {
223 errors.push(new Error(`Invalid dependency range for '${name}'`));
224 range = `*`;
225 }
226 const descriptor = structUtils.makeDescriptor(ident, range);
227 this.peerDependencies.set(descriptor.identHash, descriptor);
228 }
229 }
230 if (typeof data.workspaces === `object` && data.workspaces.nohoist)
231 errors.push(new Error(`'nohoist' is deprecated, please use 'installConfig.hoistingLimits' instead`));
232 const workspaces = Array.isArray(data.workspaces)
233 ? data.workspaces
234 : typeof data.workspaces === `object` && data.workspaces !== null && Array.isArray(data.workspaces.packages)
235 ? data.workspaces.packages
236 : [];
237 for (const entry of workspaces) {
238 if (typeof entry !== `string`) {
239 errors.push(new Error(`Invalid workspace definition for '${entry}'`));
240 continue;
241 }
242 this.workspaceDefinitions.push({
243 pattern: entry,
244 });
245 }
246 if (typeof data.dependenciesMeta === `object` && data.dependenciesMeta !== null) {
247 for (const [pattern, meta] of Object.entries(data.dependenciesMeta)) {
248 if (typeof meta !== `object` || meta === null) {
249 errors.push(new Error(`Invalid meta field for '${pattern}`));
250 continue;
251 }
252 const descriptor = structUtils.parseDescriptor(pattern);
253 const dependencyMeta = this.ensureDependencyMeta(descriptor);
254 Object.assign(dependencyMeta, meta);
255 }
256 }
257 if (typeof data.peerDependenciesMeta === `object` && data.peerDependenciesMeta !== null) {
258 for (const [pattern, meta] of Object.entries(data.peerDependenciesMeta)) {
259 if (typeof meta !== `object` || meta === null) {
260 errors.push(new Error(`Invalid meta field for '${pattern}`));
261 continue;
262 }
263 const descriptor = structUtils.parseDescriptor(pattern);
264 const peerDependencyMeta = this.ensurePeerDependencyMeta(descriptor);
265 Object.assign(peerDependencyMeta, meta);
266 }
267 }
268 if (typeof data.resolutions === `object` && data.resolutions !== null) {
269 for (const [pattern, reference] of Object.entries(data.resolutions)) {
270 if (typeof reference !== `string`) {
271 errors.push(new Error(`Invalid resolution entry for '${pattern}'`));
272 continue;
273 }
274 try {
275 this.resolutions.push({ pattern: parsers_1.parseResolution(pattern), reference });
276 }
277 catch (error) {
278 errors.push(error);
279 continue;
280 }
281 }
282 }
283 if (Array.isArray(data.files) && data.files.length !== 0) {
284 this.files = new Set();
285 for (const filename of data.files) {
286 if (typeof filename !== `string`) {
287 errors.push(new Error(`Invalid files entry for '${filename}'`));
288 continue;
289 }
290 this.files.add(filename);
291 }
292 }
293 if (typeof data.publishConfig === `object` && data.publishConfig !== null) {
294 this.publishConfig = {};
295 if (typeof data.publishConfig.access === `string`)
296 this.publishConfig.access = data.publishConfig.access;
297 if (typeof data.publishConfig.main === `string`)
298 this.publishConfig.main = data.publishConfig.main;
299 if (typeof data.publishConfig.module === `string`)
300 this.publishConfig.module = data.publishConfig.module;
301 if (typeof data.publishConfig.browser === `string`)
302 this.publishConfig.browser = data.publishConfig.browser;
303 if (typeof data.publishConfig.browser === `object` && data.publishConfig.browser !== null)
304 this.publishConfig.browser = new Map(Object.entries(data.publishConfig.browser));
305 if (typeof data.publishConfig.registry === `string`)
306 this.publishConfig.registry = data.publishConfig.registry;
307 if (typeof data.publishConfig.bin === `string`) {
308 if (this.name !== null) {
309 this.publishConfig.bin = new Map([[this.name.name, data.publishConfig.bin]]);
310 }
311 else {
312 errors.push(new Error(`String bin field, but no attached package name`));
313 }
314 }
315 else if (typeof data.publishConfig.bin === `object` && data.publishConfig.bin !== null) {
316 this.publishConfig.bin = new Map();
317 for (const [key, value] of Object.entries(data.publishConfig.bin)) {
318 if (typeof value !== `string`) {
319 errors.push(new Error(`Invalid bin definition for '${key}'`));
320 continue;
321 }
322 this.publishConfig.bin.set(key, value);
323 }
324 }
325 if (Array.isArray(data.publishConfig.executableFiles)) {
326 this.publishConfig.executableFiles = new Set();
327 for (const value of data.publishConfig.executableFiles) {
328 if (typeof value !== `string`) {
329 errors.push(new Error(`Invalid executable file definition`));
330 continue;
331 }
332 this.publishConfig.executableFiles.add(fslib_1.npath.toPortablePath(value));
333 }
334 }
335 }
336 if (typeof data.installConfig === `object` && data.installConfig !== null) {
337 this.installConfig = {};
338 for (const key of Object.keys(data.installConfig)) {
339 if (key === `hoistingLimits`) {
340 if (typeof data.installConfig.hoistingLimits === `string`) {
341 this.installConfig.hoistingLimits = data.installConfig.hoistingLimits;
342 }
343 else {
344 errors.push(new Error(`Invalid hoisting limits definition`));
345 }
346 }
347 else {
348 errors.push(new Error(`Unrecognized installConfig key: ${key}`));
349 }
350 }
351 }
352 // We treat optional dependencies after both the regular dependency field
353 // and the dependenciesMeta field have been generated (because we will
354 // override them)
355 if (typeof data.optionalDependencies === `object` && data.optionalDependencies !== null) {
356 for (const [name, range] of Object.entries(data.optionalDependencies)) {
357 if (typeof range !== `string`) {
358 errors.push(new Error(`Invalid dependency range for '${name}'`));
359 continue;
360 }
361 let ident;
362 try {
363 ident = structUtils.parseIdent(name);
364 }
365 catch (error) {
366 errors.push(new Error(`Parsing failed for the dependency name '${name}'`));
367 continue;
368 }
369 // Note that we store the optional dependencies in the same store as
370 // the one that keep the regular dependencies, because they're
371 // effectively the same (the only difference is that optional
372 // dependencies have an extra field set in dependenciesMeta).
373 const realDescriptor = structUtils.makeDescriptor(ident, range);
374 this.dependencies.set(realDescriptor.identHash, realDescriptor);
375 const identDescriptor = structUtils.makeDescriptor(ident, `unknown`);
376 const dependencyMeta = this.ensureDependencyMeta(identDescriptor);
377 Object.assign(dependencyMeta, { optional: true });
378 }
379 }
380 if (typeof data.preferUnplugged === `boolean`)
381 this.preferUnplugged = data.preferUnplugged;
382 this.errors = errors;
383 }
384 getForScope(type) {
385 switch (type) {
386 case `dependencies`:
387 return this.dependencies;
388 case `devDependencies`:
389 return this.devDependencies;
390 case `peerDependencies`:
391 return this.peerDependencies;
392 default: {
393 throw new Error(`Unsupported value ("${type}")`);
394 }
395 }
396 }
397 hasConsumerDependency(ident) {
398 if (this.dependencies.has(ident.identHash))
399 return true;
400 if (this.peerDependencies.has(ident.identHash))
401 return true;
402 return false;
403 }
404 hasHardDependency(ident) {
405 if (this.dependencies.has(ident.identHash))
406 return true;
407 if (this.devDependencies.has(ident.identHash))
408 return true;
409 return false;
410 }
411 hasSoftDependency(ident) {
412 if (this.peerDependencies.has(ident.identHash))
413 return true;
414 return false;
415 }
416 hasDependency(ident) {
417 if (this.hasHardDependency(ident))
418 return true;
419 if (this.hasSoftDependency(ident))
420 return true;
421 return false;
422 }
423 isCompatibleWithOS(os) {
424 return this.os === null || isManifestFieldCompatible(this.os, os);
425 }
426 isCompatibleWithCPU(cpu) {
427 return this.cpu === null || isManifestFieldCompatible(this.cpu, cpu);
428 }
429 ensureDependencyMeta(descriptor) {
430 if (descriptor.range !== `unknown` && !semver_1.default.valid(descriptor.range))
431 throw new Error(`Invalid meta field range for '${structUtils.stringifyDescriptor(descriptor)}'`);
432 const identString = structUtils.stringifyIdent(descriptor);
433 const range = descriptor.range !== `unknown` ? descriptor.range : null;
434 let dependencyMetaSet = this.dependenciesMeta.get(identString);
435 if (!dependencyMetaSet)
436 this.dependenciesMeta.set(identString, dependencyMetaSet = new Map());
437 let dependencyMeta = dependencyMetaSet.get(range);
438 if (!dependencyMeta)
439 dependencyMetaSet.set(range, dependencyMeta = {});
440 return dependencyMeta;
441 }
442 ensurePeerDependencyMeta(descriptor) {
443 if (descriptor.range !== `unknown`)
444 throw new Error(`Invalid meta field range for '${structUtils.stringifyDescriptor(descriptor)}'`);
445 const identString = structUtils.stringifyIdent(descriptor);
446 let peerDependencyMeta = this.peerDependenciesMeta.get(identString);
447 if (!peerDependencyMeta)
448 this.peerDependenciesMeta.set(identString, peerDependencyMeta = {});
449 return peerDependencyMeta;
450 }
451 setRawField(name, value, { after = [] } = {}) {
452 const afterSet = new Set(after.filter(key => {
453 return Object.prototype.hasOwnProperty.call(this.raw, key);
454 }));
455 if (afterSet.size === 0 || Object.prototype.hasOwnProperty.call(this.raw, name)) {
456 this.raw[name] = value;
457 }
458 else {
459 const oldRaw = this.raw;
460 const newRaw = this.raw = {};
461 let inserted = false;
462 for (const key of Object.keys(oldRaw)) {
463 newRaw[key] = oldRaw[key];
464 if (!inserted) {
465 afterSet.delete(key);
466 if (afterSet.size === 0) {
467 newRaw[name] = value;
468 inserted = true;
469 }
470 }
471 }
472 }
473 }
474 exportTo(data, { compatibilityMode = true } = {}) {
475 // Note that we even set the fields that we re-set later; it
476 // allows us to preserve the key ordering
477 Object.assign(data, this.raw);
478 if (this.name !== null)
479 data.name = structUtils.stringifyIdent(this.name);
480 else
481 delete data.name;
482 if (this.version !== null)
483 data.version = this.version;
484 else
485 delete data.version;
486 if (this.os !== null)
487 data.os = this.os;
488 else
489 delete data.os;
490 if (this.cpu !== null)
491 data.cpu = this.cpu;
492 else
493 delete data.cpu;
494 if (this.type !== null)
495 data.type = this.type;
496 else
497 delete data.type;
498 if (this.private)
499 data.private = true;
500 else
501 delete data.private;
502 if (this.license !== null)
503 data.license = this.license;
504 else
505 delete data.license;
506 if (this.languageName !== null)
507 data.languageName = this.languageName;
508 else
509 delete data.languageName;
510 if (this.main !== null)
511 data.main = this.main;
512 else
513 delete data.main;
514 if (this.module !== null)
515 data.module = this.module;
516 else
517 delete data.module;
518 if (this.browser !== null) {
519 const browser = this.browser;
520 if (typeof browser === `string`) {
521 data.browser = browser;
522 }
523 else if (browser instanceof Map) {
524 data.browser = Object.assign({}, ...Array.from(browser.keys()).sort().map(name => {
525 return { [name]: browser.get(name) };
526 }));
527 }
528 }
529 else {
530 delete data.browser;
531 }
532 if (this.bin.size === 1 && this.name !== null && this.bin.has(this.name.name)) {
533 data.bin = this.bin.get(this.name.name);
534 }
535 else if (this.bin.size > 0) {
536 data.bin = Object.assign({}, ...Array.from(this.bin.keys()).sort().map(name => {
537 return { [name]: this.bin.get(name) };
538 }));
539 }
540 else {
541 delete data.bin;
542 }
543 if (this.workspaceDefinitions.length > 0) {
544 if (this.raw.workspaces && !Array.isArray(this.raw.workspaces)) {
545 data.workspaces = { ...this.raw.workspaces, packages: this.workspaceDefinitions.map(({ pattern }) => pattern) };
546 }
547 else {
548 data.workspaces = this.workspaceDefinitions.map(({ pattern }) => pattern);
549 }
550 }
551 else if (this.raw.workspaces && !Array.isArray(this.raw.workspaces) && Object.keys(this.raw.workspaces).length > 0) {
552 data.workspaces = this.raw.workspaces;
553 }
554 else {
555 delete data.workspaces;
556 }
557 const regularDependencies = [];
558 const optionalDependencies = [];
559 for (const dependency of this.dependencies.values()) {
560 const dependencyMetaSet = this.dependenciesMeta.get(structUtils.stringifyIdent(dependency));
561 let isOptionallyBuilt = false;
562 if (compatibilityMode) {
563 if (dependencyMetaSet) {
564 const meta = dependencyMetaSet.get(null);
565 if (meta && meta.optional) {
566 isOptionallyBuilt = true;
567 }
568 }
569 }
570 if (isOptionallyBuilt) {
571 optionalDependencies.push(dependency);
572 }
573 else {
574 regularDependencies.push(dependency);
575 }
576 }
577 if (regularDependencies.length > 0) {
578 data.dependencies = Object.assign({}, ...structUtils.sortDescriptors(regularDependencies).map(dependency => {
579 return { [structUtils.stringifyIdent(dependency)]: dependency.range };
580 }));
581 }
582 else {
583 delete data.dependencies;
584 }
585 if (optionalDependencies.length > 0) {
586 data.optionalDependencies = Object.assign({}, ...structUtils.sortDescriptors(optionalDependencies).map(dependency => {
587 return { [structUtils.stringifyIdent(dependency)]: dependency.range };
588 }));
589 }
590 else {
591 delete data.optionalDependencies;
592 }
593 if (this.devDependencies.size > 0) {
594 data.devDependencies = Object.assign({}, ...structUtils.sortDescriptors(this.devDependencies.values()).map(dependency => {
595 return { [structUtils.stringifyIdent(dependency)]: dependency.range };
596 }));
597 }
598 else {
599 delete data.devDependencies;
600 }
601 if (this.peerDependencies.size > 0) {
602 data.peerDependencies = Object.assign({}, ...structUtils.sortDescriptors(this.peerDependencies.values()).map(dependency => {
603 return { [structUtils.stringifyIdent(dependency)]: dependency.range };
604 }));
605 }
606 else {
607 delete data.peerDependencies;
608 }
609 data.dependenciesMeta = {};
610 for (const [identString, dependencyMetaSet] of miscUtils.sortMap(this.dependenciesMeta.entries(), ([identString, dependencyMetaSet]) => identString)) {
611 for (const [range, meta] of miscUtils.sortMap(dependencyMetaSet.entries(), ([range, meta]) => range !== null ? `0${range}` : `1`)) {
612 const key = range !== null
613 ? structUtils.stringifyDescriptor(structUtils.makeDescriptor(structUtils.parseIdent(identString), range))
614 : identString;
615 const metaCopy = { ...meta };
616 if (compatibilityMode && range === null)
617 delete metaCopy.optional;
618 if (Object.keys(metaCopy).length === 0)
619 continue;
620 data.dependenciesMeta[key] = metaCopy;
621 }
622 }
623 if (Object.keys(data.dependenciesMeta).length === 0)
624 delete data.dependenciesMeta;
625 if (this.peerDependenciesMeta.size > 0) {
626 data.peerDependenciesMeta = Object.assign({}, ...miscUtils.sortMap(this.peerDependenciesMeta.entries(), ([identString, meta]) => identString).map(([identString, meta]) => {
627 return { [identString]: meta };
628 }));
629 }
630 else {
631 delete data.peerDependenciesMeta;
632 }
633 if (this.resolutions.length > 0) {
634 data.resolutions = Object.assign({}, ...this.resolutions.map(({ pattern, reference }) => {
635 return { [parsers_1.stringifyResolution(pattern)]: reference };
636 }));
637 }
638 else {
639 delete data.resolutions;
640 }
641 if (this.files !== null)
642 data.files = Array.from(this.files);
643 else
644 delete data.files;
645 if (this.preferUnplugged !== null)
646 data.preferUnplugged = this.preferUnplugged;
647 else
648 delete data.preferUnplugged;
649 return data;
650 }
651}
652exports.Manifest = Manifest;
653Manifest.fileName = `package.json`;
654Manifest.allDependencies = [`dependencies`, `devDependencies`, `peerDependencies`];
655Manifest.hardDependencies = [`dependencies`, `devDependencies`];
656function getIndent(content) {
657 const indentMatch = content.match(/^[ \t]+/m);
658 if (indentMatch) {
659 return indentMatch[0];
660 }
661 else {
662 return ` `;
663 }
664}
665function stripBOM(content) {
666 if (content.charCodeAt(0) === 0xFEFF) {
667 return content.slice(1);
668 }
669 else {
670 return content;
671 }
672}
673function isManifestFieldCompatible(rules, actual) {
674 let isNotWhitelist = true;
675 let isBlacklist = false;
676 for (const rule of rules) {
677 if (rule[0] === `!`) {
678 isBlacklist = true;
679 if (actual === rule.slice(1)) {
680 return false;
681 }
682 }
683 else {
684 isNotWhitelist = false;
685 if (rule === actual) {
686 return true;
687 }
688 }
689 }
690 // Blacklists with whitelisted items should be treated as whitelists for `os` and `cpu` in `package.json`
691 return isBlacklist && isNotWhitelist;
692}