UNPKG

3.2 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2015-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8'use strict';
9
10const chalk = require('chalk');
11const path = require('path');
12const os = require('os');
13
14class ModuleScopePlugin {
15 constructor(appSrc, allowedFiles = []) {
16 this.appSrcs = Array.isArray(appSrc) ? appSrc : [appSrc];
17 this.allowedFiles = new Set(allowedFiles);
18 }
19
20 apply(resolver) {
21 const { appSrcs } = this;
22 resolver.hooks.file.tapAsync(
23 'ModuleScopePlugin',
24 (request, contextResolver, callback) => {
25 // Unknown issuer, probably webpack internals
26 if (!request.context.issuer) {
27 return callback();
28 }
29 if (
30 // If this resolves to a node_module, we don't care what happens next
31 request.descriptionFileRoot.indexOf('/node_modules/') !== -1 ||
32 request.descriptionFileRoot.indexOf('\\node_modules\\') !== -1 ||
33 // Make sure this request was manual
34 !request.__innerRequest_request
35 ) {
36 return callback();
37 }
38 // Resolve the issuer from our appSrc and make sure it's one of our files
39 // Maybe an indexOf === 0 would be better?
40 if (
41 appSrcs.every(appSrc => {
42 const relative = path.relative(appSrc, request.context.issuer);
43 // If it's not in one of our app src or a subdirectory, not our request!
44 return relative.startsWith('../') || relative.startsWith('..\\');
45 })
46 ) {
47 return callback();
48 }
49 const requestFullPath = path.resolve(
50 path.dirname(request.context.issuer),
51 request.__innerRequest_request
52 );
53 if (this.allowedFiles.has(requestFullPath)) {
54 return callback();
55 }
56 // Find path from src to the requested file
57 // Error if in a parent directory of all given appSrcs
58 if (
59 appSrcs.every(appSrc => {
60 const requestRelative = path.relative(appSrc, requestFullPath);
61 return (
62 requestRelative.startsWith('../') ||
63 requestRelative.startsWith('..\\')
64 );
65 })
66 ) {
67 const scopeError = new Error(
68 `You attempted to import ${chalk.cyan(
69 request.__innerRequest_request
70 )} which falls outside of the project ${chalk.cyan(
71 'src/'
72 )} directory. ` +
73 `Relative imports outside of ${chalk.cyan(
74 'src/'
75 )} are not supported.` +
76 os.EOL +
77 `You can either move it inside ${chalk.cyan(
78 'src/'
79 )}, or add a symlink to it from project's ${chalk.cyan(
80 'node_modules/'
81 )}.`
82 );
83 Object.defineProperty(scopeError, '__module_scope_plugin', {
84 value: true,
85 writable: false,
86 enumerable: false,
87 });
88 callback(scopeError, request);
89 } else {
90 callback();
91 }
92 }
93 );
94 }
95}
96
97module.exports = ModuleScopePlugin;