1'use strict';
2
3var test = require('tape');
4var keys = require('object-keys');
5var semver = require('semver');
6var mockProperty = require('mock-property');
7
8var isCore = require('../');
9var data = require('../core.json');
10
11var supportsNodePrefix = semver.satisfies(process.versions.node, '^14.18 || >= 16', { includePrerelease: true });
12
13test('core modules', function (t) {
14	t.test('isCore()', function (st) {
15		st.ok(isCore('fs'));
16		st.ok(isCore('net'));
17		st.ok(isCore('http'));
18
19		st.ok(!isCore('seq'));
20		st.ok(!isCore('../'));
21
22		st.ok(!isCore('toString'));
23
24		st.end();
25	});
26
27	t.test('core list', function (st) {
28		var cores = keys(data);
29		st.plan(cores.length);
30
31		for (var i = 0; i < cores.length; ++i) {
32			var mod = cores[i];
33			var requireFunc = function () { require(mod); }; // eslint-disable-line no-loop-func
34			if (isCore(mod)) {
35				st.doesNotThrow(requireFunc, mod + ' supported; requiring does not throw');
36			} else {
37				st['throws'](requireFunc, mod + ' not supported; requiring throws');
38			}
39		}
40
41		st.end();
42	});
43
44	t.test('core via repl module', { skip: !data.repl }, function (st) {
45		var libs = require('repl')._builtinLibs; // eslint-disable-line no-underscore-dangle
46		if (!libs) {
47			st.skip('repl._builtinLibs does not exist');
48		} else {
49			for (var i = 0; i < libs.length; ++i) {
50				var mod = libs[i];
51				st.ok(data[mod], mod + ' is a core module');
52				st.doesNotThrow(
53					function () { require(mod); }, // eslint-disable-line no-loop-func
54					'requiring ' + mod + ' does not throw'
55				);
56				if (mod.slice(0, 5) !== 'node:') {
57					if (supportsNodePrefix) {
58						st.doesNotThrow(
59							function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
60							'requiring node:' + mod + ' does not throw'
61						);
62					} else {
63						st['throws'](
64							function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
65							'requiring node:' + mod + ' throws'
66						);
67					}
68				}
69			}
70		}
71		st.end();
72	});
73
74	t.test('core via builtinModules list', { skip: !data.module }, function (st) {
75		var libs = require('module').builtinModules;
76		if (!libs) {
77			st.skip('module.builtinModules does not exist');
78		} else {
79			var excludeList = [
80				'_debug_agent',
81				'v8/tools/tickprocessor-driver',
82				'v8/tools/SourceMap',
83				'v8/tools/tickprocessor',
84				'v8/tools/profile'
85			];
86			// see https://github.com/nodejs/node/issues/42785
87			if (semver.satisfies(process.version, '>= 18')) {
88				libs = libs.concat('node:test');
89			}
90			for (var i = 0; i < libs.length; ++i) {
91				var mod = libs[i];
92				if (excludeList.indexOf(mod) === -1) {
93					st.ok(data[mod], mod + ' is a core module');
94					st.doesNotThrow(
95						function () { require(mod); }, // eslint-disable-line no-loop-func
96						'requiring ' + mod + ' does not throw'
97					);
98					if (mod.slice(0, 5) !== 'node:') {
99						if (supportsNodePrefix) {
100							st.doesNotThrow(
101								function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
102								'requiring node:' + mod + ' does not throw'
103							);
104						} else {
105							st['throws'](
106								function () { require('node:' + mod); }, // eslint-disable-line no-loop-func
107								'requiring node:' + mod + ' throws'
108							);
109						}
110					}
111				}
112			}
113		}
114		st.end();
115	});
116
117	t.test('Object.prototype pollution', function (st) {
118		var nonKey = 'not a core module';
119		st.teardown(mockProperty(Object.prototype, 'fs', { value: false }));
120		st.teardown(mockProperty(Object.prototype, 'path', { value: '>= 999999999' }));
121		st.teardown(mockProperty(Object.prototype, 'http', { value: data.http }));
122		st.teardown(mockProperty(Object.prototype, nonKey, { value: true }));
123
124		st.equal(isCore('fs'), true, 'fs is a core module even if Object.prototype lies');
125		st.equal(isCore('path'), true, 'path is a core module even if Object.prototype lies');
126		st.equal(isCore('http'), true, 'path is a core module even if Object.prototype matches data');
127		st.equal(isCore(nonKey), false, '"' + nonKey + '" is not a core module even if Object.prototype lies');
128
129		st.end();
130	});
131
132	t.end();
133});
134