Remove fastpath

Summary: I originally added fastpath to node-haste to speed up `path` operations by an order of magnitude. Now we are exclusively using Node 6 at FB so we don't need to ship this thing any more.

Reviewed By: bestander

Differential Revision: D4029092

fbshipit-source-id: 064cf67f4f79ce4f2774fb4e430d22eef4a95434
This commit is contained in:
Christoph Pojer 2016-10-20 00:12:21 -07:00 committed by Facebook Github Bot
parent c16465a582
commit 18c4ae81e7
18 changed files with 53 additions and 1216 deletions

View File

@ -10,8 +10,6 @@
require('../babelRegisterOnly')([/react-packager\/src/]); require('../babelRegisterOnly')([/react-packager\/src/]);
require('./src/node-haste/fastpath').replace();
var debug = require('debug'); var debug = require('debug');
var Activity = require('./src/Activity'); var Activity = require('./src/Activity');

View File

@ -1,11 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
module.exports = require.requireActual('../node-haste/__mocks__/graceful-fs');

View File

@ -1,11 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
module.exports = require('fs');

View File

@ -8,11 +8,11 @@
*/ */
'use strict'; 'use strict';
const denodeify = require('denodeify');
const crypto = require('crypto'); const crypto = require('crypto');
const denodeify = require('denodeify');
const fs = require('graceful-fs'); const fs = require('graceful-fs');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const path = require('../fastpath'); const path = require('path');
const tmpDir = require('os').tmpDir(); const tmpDir = require('os').tmpDir();
function getObjectValues(object) { function getObjectValues(object) {

View File

@ -8,7 +8,7 @@
*/ */
'use strict'; 'use strict';
const path = require('../fastpath'); const path = require('path');
const NODE_MODULES = path.sep + 'node_modules' + path.sep; const NODE_MODULES = path.sep + 'node_modules' + path.sep;

View File

@ -10,7 +10,7 @@
const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED'); const AssetModule_DEPRECATED = require('../AssetModule_DEPRECATED');
const debug = require('debug')('ReactNativePackager:DependencyGraph'); const debug = require('debug')('ReactNativePackager:DependencyGraph');
const path = require('../fastpath'); const path = require('path');
class DeprecatedAssetMap { class DeprecatedAssetMap {
constructor({ constructor({

View File

@ -10,8 +10,8 @@
const EventEmitter = require('events'); const EventEmitter = require('events');
const path = require('../fastpath');
const getPlatformExtension = require('../lib/getPlatformExtension'); const getPlatformExtension = require('../lib/getPlatformExtension');
const path = require('path');
const throat = require('throat'); const throat = require('throat');
const GENERIC_PLATFORM = 'generic'; const GENERIC_PLATFORM = 'generic';
@ -98,7 +98,7 @@ class HasteMap extends EventEmitter {
// If platform is 'ios', we prefer .ios.js to .native.js which we prefer to // If platform is 'ios', we prefer .ios.js to .native.js which we prefer to
// a plain .js file. // a plain .js file.
let module = undefined; let module;
if (module == null && platform != null) { if (module == null && platform != null) {
module = modulesMap[platform]; module = modulesMap[platform];
} }

View File

@ -12,7 +12,7 @@ const AsyncTaskGroup = require('../lib/AsyncTaskGroup');
const MapWithDefaults = require('../lib/MapWithDefaults'); const MapWithDefaults = require('../lib/MapWithDefaults');
const debug = require('debug')('ReactNativePackager:DependencyGraph'); const debug = require('debug')('ReactNativePackager:DependencyGraph');
const util = require('util'); const util = require('util');
const path = require('../fastpath'); const path = require('path');
const realPath = require('path'); const realPath = require('path');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const getAssetDataFromName = require('../lib/getAssetDataFromName'); const getAssetDataFromName = require('../lib/getAssetDataFromName');
@ -358,7 +358,7 @@ class ResolutionRequest {
for (let currDir = path.dirname(fromModule.path); for (let currDir = path.dirname(fromModule.path);
currDir !== realPath.parse(fromModule.path).root; currDir !== realPath.parse(fromModule.path).root;
currDir = path.dirname(currDir)) { currDir = path.dirname(currDir)) {
let searchPath = path.join(currDir, 'node_modules'); const searchPath = path.join(currDir, 'node_modules');
if (this._fastfs.dirExists(searchPath)) { if (this._fastfs.dirExists(searchPath)) {
searchQueue.push( searchQueue.push(
path.join(searchPath, realModuleName) path.join(searchPath, realModuleName)
@ -399,7 +399,7 @@ class ResolutionRequest {
`To resolve try the following:\n` + `To resolve try the following:\n` +
` 1. Clear watchman watches: \`watchman watch-del-all\`.\n` + ` 1. Clear watchman watches: \`watchman watch-del-all\`.\n` +
` 2. Delete the \`node_modules\` folder: \`rm -rf node_modules && npm install\`.\n` + ` 2. Delete the \`node_modules\` folder: \`rm -rf node_modules && npm install\`.\n` +
` 3. Reset packager cache: \`rm -fr $TMPDIR/react-*\` or \`npm start -- --reset-cache\`.` ' 3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start -- --reset-cache`.'
); );
}); });
}); });

View File

@ -13,7 +13,7 @@ const docblock = require('./DependencyGraph/docblock');
const extractRequires = require('./lib/extractRequires'); const extractRequires = require('./lib/extractRequires');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const jsonStableStringify = require('json-stable-stringify'); const jsonStableStringify = require('json-stable-stringify');
const path = require('./fastpath'); const path = require('path');
class Module { class Module {

View File

@ -1,10 +1,20 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict'; 'use strict';
const AssetModule = require('./AssetModule'); const AssetModule = require('./AssetModule');
const Package = require('./Package');
const Module = require('./Module'); const Module = require('./Module');
const Package = require('./Package');
const Polyfill = require('./Polyfill'); const Polyfill = require('./Polyfill');
const path = require('./fastpath');
const path = require('path');
class ModuleCache { class ModuleCache {

View File

@ -1,7 +1,16 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict'; 'use strict';
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const path = require('./fastpath'); const path = require('path');
class Package { class Package {

View File

@ -1,11 +0,0 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
module.exports = () => () => {};

View File

@ -39,9 +39,7 @@ jest.mock('jest-haste-map/build/crawlers/node', () => {
activeCalls--; activeCalls--;
names.forEach(file => { names.forEach(file => {
file = process.platform === 'win32' ? file = path.join(directory, file);
path.win32.join(directory, file) :
path.join(directory, file);
if (ignore(file)) { if (ignore(file)) {
return; return;
} }
@ -109,6 +107,13 @@ const mocksPattern = /(?:[\\/]|^)__mocks__[\\/]([^\/]+)\.js$/;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
const path = require('path');
beforeEach(() => {
jest.resetModules();
jest.mock('path', () => path);
});
describe('DependencyGraph', function() { describe('DependencyGraph', function() {
let Module; let Module;
let defaults; let defaults;
@ -2715,8 +2720,9 @@ describe('DependencyGraph', function() {
beforeEach(function() { beforeEach(function() {
process.platform = 'win32'; process.platform = 'win32';
// force reload with fastpath // reload path module
jest.resetModules(); jest.resetModules();
jest.mock('path', () => path.win32);
DependencyGraph = require('../index'); DependencyGraph = require('../index');
}); });

View File

@ -1,535 +0,0 @@
/**
* Copyright (c) 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* original author: dead_horse <dead_horse@qq.com>
* ported by: yaycmyk <evan@yaycmyk.com>
*/
jest.dontMock('../fastpath');
const fp = () => require('../fastpath');
describe('fast-path', () => {
const actual_platform = process.platform;
const invalidInputTests = [
true,
false,
7,
null,
{},
undefined,
[],
NaN,
() => {},
];
const getErrorMessage = (fnName, test, expected, actual) => {
return [
`fastpath.${fnName}('${test}')`,
`expect=${JSON.stringify(expected)}`,
`actual=${JSON.stringify(actual)}`,
].join('\n');
};
beforeEach(function() {
jest.resetModules();
process.platform = 'linux';
});
afterEach(function() {
process.platform = actual_platform;
});
describe('basename', () => {
it('should resolve given paths', () => {
process.platform = actual_platform;
expect(fp().basename(__filename)).toEqual('fastpath-test.js');
expect(fp().basename(__filename, '.js')).toEqual('fastpath-test');
expect(fp().basename('')).toEqual('');
expect(fp().basename('/dir/basename.ext')).toEqual('basename.ext');
expect(fp().basename('/basename.ext')).toEqual('basename.ext');
expect(fp().basename('basename.ext')).toEqual('basename.ext');
expect(fp().basename('basename.ext/')).toEqual('basename.ext');
expect(fp().basename('basename.ext//')).toEqual('basename.ext');
});
it('should handle backslashes properly (win32)', () => {
process.platform = 'win32';
expect(fp().basename('\\dir\\basename.ext')).toEqual('basename.ext');
expect(fp().basename('\\basename.ext')).toEqual('basename.ext');
expect(fp().basename('basename.ext')).toEqual('basename.ext');
expect(fp().basename('basename.ext\\')).toEqual('basename.ext');
expect(fp().basename('basename.ext\\\\')).toEqual('basename.ext');
});
it('should handle backslashes properly (posix)', () => {
expect(fp().basename('\\dir\\basename.ext')).toEqual('\\dir\\basename.ext');
expect(fp().basename('\\basename.ext')).toEqual('\\basename.ext');
expect(fp().basename('basename.ext')).toEqual('basename.ext');
expect(fp().basename('basename.ext\\')).toEqual('basename.ext\\');
expect(fp().basename('basename.ext\\\\')).toEqual('basename.ext\\\\');
});
it('should handle control characters (posix)', () => {
// POSIX filenames may include control characters
// c.f. http://www.dwheeler.com/essays/fixing-unix-linux-filenames.html
const name = 'Icon' + String.fromCharCode(13);
expect(fp().basename('/a/b/' + name)).toEqual(name);
});
});
describe('extname', () => {
it('should extract the extension from a path', () => {
process.platform = actual_platform;
expect(fp().extname(__filename)).toEqual('.js');
expect(fp().extname('')).toEqual('');
expect(fp().extname('/path/to/file')).toEqual('');
expect(fp().extname('/path/to/file.ext')).toEqual('.ext');
expect(fp().extname('/path.to/file.ext')).toEqual('.ext');
expect(fp().extname('/path.to/file')).toEqual('');
expect(fp().extname('/path.to/.file')).toEqual('');
expect(fp().extname('/path.to/.file.ext')).toEqual('.ext');
expect(fp().extname('/path/to/f.ext')).toEqual('.ext');
expect(fp().extname('/path/to/..ext')).toEqual('.ext');
expect(fp().extname('file')).toEqual('');
expect(fp().extname('file.ext')).toEqual('.ext');
expect(fp().extname('.file')).toEqual('');
expect(fp().extname('.file.ext')).toEqual('.ext');
expect(fp().extname('/file')).toEqual('');
expect(fp().extname('/file.ext')).toEqual('.ext');
expect(fp().extname('/.file')).toEqual('');
expect(fp().extname('/.file.ext')).toEqual('.ext');
expect(fp().extname('.path/file.ext')).toEqual('.ext');
expect(fp().extname('file.ext.ext')).toEqual('.ext');
expect(fp().extname('file.')).toEqual('.');
expect(fp().extname('.')).toEqual('');
expect(fp().extname('./')).toEqual('');
expect(fp().extname('.file.ext')).toEqual('.ext');
expect(fp().extname('.file')).toEqual('');
expect(fp().extname('.file.')).toEqual('.');
expect(fp().extname('.file..')).toEqual('.');
expect(fp().extname('..')).toEqual('');
expect(fp().extname('../')).toEqual('');
expect(fp().extname('..file.ext')).toEqual('.ext');
expect(fp().extname('..file')).toEqual('.file');
expect(fp().extname('..file.')).toEqual('.');
expect(fp().extname('..file..')).toEqual('.');
expect(fp().extname('...')).toEqual('.');
expect(fp().extname('...ext')).toEqual('.ext');
expect(fp().extname('....')).toEqual('.');
expect(fp().extname('file.ext/')).toEqual('.ext');
expect(fp().extname('file.ext//')).toEqual('.ext');
expect(fp().extname('file/')).toEqual('');
expect(fp().extname('file//')).toEqual('');
expect(fp().extname('file./')).toEqual('.');
expect(fp().extname('file.//')).toEqual('.');
});
it('should handle path backslashes (win32)', () => {
process.platform = 'win32';
// On windows, backspace is a path separator.
expect(fp().extname('.\\')).toEqual('');
expect(fp().extname('..\\')).toEqual('');
expect(fp().extname('file.ext\\')).toEqual('.ext');
expect(fp().extname('file.ext\\\\')).toEqual('.ext');
expect(fp().extname('file\\')).toEqual('');
expect(fp().extname('file\\\\')).toEqual('');
expect(fp().extname('file.\\')).toEqual('.');
expect(fp().extname('file.\\\\')).toEqual('.');
});
it('should handle path backslashes (posix)', () => {
// On unix, backspace is a valid name component like any other character.
expect(fp().extname('.\\')).toEqual('');
expect(fp().extname('..\\')).toEqual('.\\');
expect(fp().extname('file.ext\\')).toEqual('.ext\\');
expect(fp().extname('file.ext\\\\')).toEqual('.ext\\\\');
expect(fp().extname('file\\')).toEqual('');
expect(fp().extname('file\\\\')).toEqual('');
expect(fp().extname('file.\\')).toEqual('.\\');
expect(fp().extname('file.\\\\')).toEqual('.\\\\');
});
});
describe('dirname', () => {
it('should isolate the directory name from a path (posix)', () => {
expect(fp().dirname('/a/b/')).toEqual('/a');
expect(fp().dirname('/a/b')).toEqual('/a');
expect(fp().dirname('/a')).toEqual('/');
expect(fp().dirname('')).toEqual('.');
expect(fp().dirname('/')).toEqual('/');
expect(fp().dirname('////')).toEqual('/');
});
it('should isolate the directory name from a path (win32)', () => {
process.platform = 'win32';
expect(fp().dirname('C:\\')).toEqual('C:\\');
expect(fp().dirname('c:\\')).toEqual('c:\\');
expect(fp().dirname('c:\\foo')).toEqual('c:\\');
expect(fp().dirname('c:\\foo\\')).toEqual('c:\\');
expect(fp().dirname('c:\\foo\\bar')).toEqual('c:\\foo');
expect(fp().dirname('c:\\foo\\bar\\')).toEqual('c:\\foo');
expect(fp().dirname('c:\\foo\\bar\\baz')).toEqual('c:\\foo\\bar');
expect(fp().dirname('\\')).toEqual('\\');
expect(fp().dirname('\\foo')).toEqual('\\');
expect(fp().dirname('\\foo\\')).toEqual('\\');
expect(fp().dirname('\\foo\\bar')).toEqual('\\foo');
expect(fp().dirname('\\foo\\bar\\')).toEqual('\\foo');
expect(fp().dirname('\\foo\\bar\\baz')).toEqual('\\foo\\bar');
expect(fp().dirname('c:')).toEqual('c:');
expect(fp().dirname('c:foo')).toEqual('c:');
expect(fp().dirname('c:foo\\')).toEqual('c:');
expect(fp().dirname('c:foo\\bar')).toEqual('c:foo');
expect(fp().dirname('c:foo\\bar\\')).toEqual('c:foo');
expect(fp().dirname('c:foo\\bar\\baz')).toEqual('c:foo\\bar');
expect(fp().dirname('\\\\unc\\share')).toEqual('\\\\unc\\share');
expect(fp().dirname('\\\\unc\\share\\foo')).toEqual('\\\\unc\\share\\');
expect(fp().dirname('\\\\unc\\share\\foo\\')).toEqual('\\\\unc\\share\\');
expect(fp().dirname('\\\\unc\\share\\foo\\bar')).toEqual('\\\\unc\\share\\foo');
expect(fp().dirname('\\\\unc\\share\\foo\\bar\\')).toEqual('\\\\unc\\share\\foo');
expect(fp().dirname('\\\\unc\\share\\foo\\bar\\baz')).toEqual('\\\\unc\\share\\foo\\bar');
});
});
describe('join', () => {
const posixJoinTests = [
// arguments result
[['.', 'x/b', '..', '/b/c.js'], 'x/b/c.js'],
[['/.', 'x/b', '..', '/b/c.js'], '/x/b/c.js'],
[['/foo', '../../../bar'], '/bar'],
[['foo', '../../../bar'], '../../bar'],
[['foo/', '../../../bar'], '../../bar'],
[['foo/x', '../../../bar'], '../bar'],
[['foo/x', './bar'], 'foo/x/bar'],
[['foo/x/', './bar'], 'foo/x/bar'],
[['foo/x/', '.', 'bar'], 'foo/x/bar'],
[['./'], './'],
[['.', './'], './'],
[['.', '.', '.'], '.'],
[['.', './', '.'], '.'],
[['.', '/./', '.'], '.'],
[['.', '/////./', '.'], '.'],
[['.'], '.'],
[['', '.'], '.'],
[['', 'foo'], 'foo'],
[['foo', '/bar'], 'foo/bar'],
[['', '/foo'], '/foo'],
[['', '', '/foo'], '/foo'],
[['', '', 'foo'], 'foo'],
[['foo', ''], 'foo'],
[['foo/', ''], 'foo/'],
[['foo', '', '/bar'], 'foo/bar'],
[['./', '..', '/foo'], '../foo'],
[['./', '..', '..', '/foo'], '../../foo'],
[['.', '..', '..', '/foo'], '../../foo'],
[['', '..', '..', '/foo'], '../../foo'],
[['/'], '/'],
[['/', '.'], '/'],
[['/', '..'], '/'],
[['/', '..', '..'], '/'],
[[''], '.'],
[['', ''], '.'],
[[' /foo'], ' /foo'],
[[' ', 'foo'], ' /foo'],
[[' ', '.'], ' '],
[[' ', '/'], ' /'],
[[' ', ''], ' '],
[['/', 'foo'], '/foo'],
[['/', '/foo'], '/foo'],
[['/', '//foo'], '/foo'],
[['/', '', '/foo'], '/foo'],
[['', '/', 'foo'], '/foo'],
[['', '/', '/foo'], '/foo'],
];
const win32JoinTests = posixJoinTests.concat([
// UNC path expected
[['//foo/bar'], '//foo/bar/'],
[['\\/foo/bar'], '//foo/bar/'],
[['\\\\foo/bar'], '//foo/bar/'],
// UNC path expected - server and share separate
[['//foo', 'bar'], '//foo/bar/'],
[['//foo/', 'bar'], '//foo/bar/'],
[['//foo', '/bar'], '//foo/bar/'],
// UNC path expected - questionable
[['//foo', '', 'bar'], '//foo/bar/'],
[['//foo/', '', 'bar'], '//foo/bar/'],
[['//foo/', '', '/bar'], '//foo/bar/'],
// UNC path expected - even more questionable
[['', '//foo', 'bar'], '//foo/bar/'],
[['', '//foo/', 'bar'], '//foo/bar/'],
[['', '//foo/', '/bar'], '//foo/bar/'],
// No UNC path expected (no double slash in first component)
[['\\', 'foo/bar'], '/foo/bar'],
[['\\', '/foo/bar'], '/foo/bar'],
[['', '/', '/foo/bar'], '/foo/bar'],
// No UNC path expected (no non-slashes in first component - questionable)
[['//', 'foo/bar'], '/foo/bar'],
[['//', '/foo/bar'], '/foo/bar'],
[['\\\\', '/', '/foo/bar'], '/foo/bar'],
[['//'], '/'],
// No UNC path expected (share name missing - questionable).
[['//foo'], '/foo'],
[['//foo/'], '/foo/'],
[['//foo', '/'], '/foo/'],
[['//foo', '', '/'], '/foo/'],
// No UNC path expected (too many leading slashes - questionable)
[['///foo/bar'], '/foo/bar'],
[['////foo', 'bar'], '/foo/bar'],
[['\\\\\\/foo/bar'], '/foo/bar'],
// Drive-relative vs drive-absolute paths. This merely describes the
// status quo, rather than being obviously right
[['C:'], 'C:.'],
[['c:'], 'c:.'],
[['c:.'], 'c:.'],
[['c:', ''], 'c:.'],
[['', 'c:'], 'c:.'],
[['c:.', '/'], 'c:./'],
[['c:.', 'file'], 'c:file'],
[['c:', '/'], 'c:/'],
[['c:', 'file'], 'c:/file'],
]);
it('should join the paths correctly (posix)', () => {
posixJoinTests.forEach((test) => {
const actual = fp().join(...test[0]);
const expected = test[1];
expect(actual).toEqual(expected, getErrorMessage('join',
test[0].map(JSON.stringify).join(','),
expected,
actual,
));
});
});
it('should join the paths correctly (win32)', () => {
process.platform = 'win32';
win32JoinTests.forEach((test) => {
const actual = fp().join(...test[0]);
const expected = test[1].replace(/\//g, '\\');
expect(actual).toEqual(expected, getErrorMessage('join',
test[0].map(JSON.stringify).join(','),
expected,
actual,
));
});
});
it('should throw for invalid input', () => {
invalidInputTests.forEach((test) => {
expect(() => fp().join(test)).toThrow();
});
});
});
describe('normalize', () => {
it('should return a valid path (posix)', () => {
expect(fp().normalize('./fixtures///b/../b/c.js')).toEqual('fixtures/b/c.js');
expect(fp().normalize('/foo/../../../bar')).toEqual('/bar');
expect(fp().normalize('a//b//../b')).toEqual('a/b');
expect(fp().normalize('a//b//./c')).toEqual('a/b/c');
expect(fp().normalize('a//b//.')).toEqual('a/b');
});
it('should return a valid path (win32)', () => {
process.platform = 'win32';
expect(fp().normalize('./fixtures///b/../b/c.js')).toEqual('fixtures\\b\\c.js');
expect(fp().normalize('/foo/../../../bar')).toEqual('\\bar');
expect(fp().normalize('a//b//../b')).toEqual('a\\b');
expect(fp().normalize('a//b//./c')).toEqual('a\\b\\c');
expect(fp().normalize('a//b//.')).toEqual('a\\b');
expect(fp().normalize('//server/share/dir/file.ext')).toEqual('\\\\server\\share\\dir\\file.ext');
});
});
describe('resolve', () => {
const win32ResolveTests = [
// arguments result
[['C:/blah\\blah', 'D:/games', 'C:../a'], 'C:\\blah\\a'],
[['c:/blah\\blah', 'd:/games', 'c:../a'], 'c:\\blah\\a'],
[['c:/ignore', 'd:\\a/b\\c/d', '\\e.exe'], 'd:\\e.exe'],
[['c:/ignore', 'c:/some/file'], 'c:\\some\\file'],
[['d:/ignore', 'd:some/dir//'], 'd:\\ignore\\some\\dir'],
[['//server/share', '..', 'relative\\'], '\\\\server\\share\\relative'],
[['c:/', '//'], 'c:\\'],
[['c:/', '//dir'], 'c:\\dir'],
[['c:/', '//server/share'], '\\\\server\\share\\'],
[['c:/', '//server//share'], '\\\\server\\share\\'],
[['c:/', '///some//dir'], 'c:\\some\\dir'],
];
const posixResolveTests = [
// arguments result
[['/var/lib', '../', 'file/'], '/var/file'],
[['/var/lib', '/../', 'file/'], '/file'],
[['/some/dir', '.', '/absolute/'], '/absolute'],
];
it('should resolve the current working directory', () => {
process.platform = actual_platform;
const actual = fp().resolve('.');
const expected = process.cwd();
expect(actual).toEqual(expected, getErrorMessage('resolve', '.', expected, actual));
});
it('should resolve paths (posix)', () => {
posixResolveTests.forEach((test) => {
const actual = fp().resolve(...test[0]);
const expected = test[1];
expect(actual).toEqual(expected, getErrorMessage('resolve', test, expected, actual));
});
});
it('should resolve paths (win32)', () => {
process.platform = 'win32';
win32ResolveTests.forEach((test) => {
const actual = fp().resolve(...test[0]);
const expected = test[1];
expect(actual).toEqual(expected, getErrorMessage('resolve', test, expected, actual));
});
});
it('should throw for invalid input', () => {
invalidInputTests.forEach((test) => {
expect(() => fp().resolve(test)).toThrow();
});
});
});
describe('isAbsolute', () => {
it('should work (posix)', () => {
expect(fp().isAbsolute('/home/foo')).toEqual(true);
expect(fp().isAbsolute('/home/foo/..')).toEqual(true);
expect(fp().isAbsolute('bar/')).toEqual(false);
expect(fp().isAbsolute('./baz')).toEqual(false);
});
it('should work (win32)', () => {
process.platform = 'win32';
expect(fp().isAbsolute('//server/file')).toEqual(true);
expect(fp().isAbsolute('\\\\server\\file')).toEqual(true);
expect(fp().isAbsolute('C:/Users/')).toEqual(true);
expect(fp().isAbsolute('C:\\Users\\')).toEqual(true);
expect(fp().isAbsolute('C:cwd/another')).toEqual(false);
expect(fp().isAbsolute('C:cwd\\another')).toEqual(false);
expect(fp().isAbsolute('directory/directory')).toEqual(false);
expect(fp().isAbsolute('directory\\directory')).toEqual(false);
});
});
describe('relative', () => {
const win32RelativeTests = [
// arguments result
['C:/blah\\blah', 'D:/games', 'D:\\games'],
['c:/blah\\blah', 'd:/games', 'd:\\games'],
['c:/aaaa/bbbb', 'c:/aaaa', '..'],
['c:/aaaa/bbbb', 'c:/cccc', '..\\..\\cccc'],
['c:/aaaa/bbbb', 'c:/aaaa/bbbb', ''],
['c:/aaaa/bbbb', 'c:/aaaa/cccc', '..\\cccc'],
['c:/aaaa/', 'c:/aaaa/cccc', 'cccc'],
['c:/', 'c:\\aaaa\\bbbb', 'aaaa\\bbbb'],
['c:/aaaa/bbbb', 'd:\\', 'd:\\'],
];
const posixRelativeTests = [
// arguments result
['/var/lib', '/var', '..'],
['/var/lib', '/bin', '../../bin'],
['/var/lib', '/var/lib', ''],
['/var/lib', '/var/apache', '../apache'],
['/var/', '/var/lib', 'lib'],
['/', '/var/lib', 'var/lib'],
];
it('should work (posix)', () => {
posixRelativeTests.forEach((test) => {
const actual = fp().relative(test[0], test[1]);
const expected = test[2];
expect(actual).toEqual(expected, getErrorMessage('relative',
test.slice(0, 2).map(JSON.stringify).join(','),
expected,
actual,
));
});
});
it('should work (win32)', () => {
process.platform = 'win32';
win32RelativeTests.forEach((test) => {
const actual = fp().relative(test[0], test[1]);
const expected = test[2];
expect(actual).toEqual(expected, getErrorMessage('relative',
test.slice(0, 2).map(JSON.stringify).join(','),
expected,
actual,
));
});
});
});
describe('(static export) sep', () => {
it('should be a backslash (win32)', () => {
process.platform = 'win32';
expect(fp().sep).toEqual('\\');
});
it('should be a forward slash (posix)', () => {
expect(fp().sep).toEqual('/');
});
});
describe('(static export) delimiter', () => {
it('should be a semicolon (win32)', () => {
process.platform = 'win32';
expect(fp().delimiter).toEqual(';');
});
it('should be a colon (posix)', () => {
expect(fp().delimiter).toEqual(':');
});
});
});

View File

@ -9,7 +9,7 @@
'use strict'; 'use strict';
const fs = require('fs'); const fs = require('fs');
const path = require('./fastpath'); const path = require('path');
const {EventEmitter} = require('events'); const {EventEmitter} = require('events');

View File

@ -1,619 +0,0 @@
/*!
* fast-path - index.js
* MIT License
*
* Copyright Joyent, Inc. and other Node contributors.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* original author: dead_horse <dead_horse@qq.com>
* ported by: yaycmyk <evan@yaycmyk.com>
*
* VERSION 1.2.0
*/
'use strict';
const fs = require('fs');
const path = require('path');
const util = require('util');
const all = Object.keys(exports).filter((name) => name !== 'replace');
const IS_WINDOWS = process.platform === 'win32';
function isString(arg) {
return typeof arg === 'string';
}
const splitDeviceRe =
/^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
function getDevice(filename) {
const result = splitDeviceRe.exec(filename);
return (result[1] || '') + (result[2] || '');
}
// resolves . and .. elements in a path array with directory names there
// must be no slashes, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
const nonEmptyParts = [];
let nonBack = true;
for (let i = 0; i < parts.length; i++) {
const p = parts[i];
if (p && p !== '.') {
nonEmptyParts.push(p);
}
if (p === '..') {
nonBack = false;
}
}
parts = nonEmptyParts;
// if the path does not contain ..
if (nonBack) {
return parts;
}
// if the path tries to go ab ove the root, `up` ends up > 0
let up = 0;
const res = [];
for (let i = parts.length - 1; i >= 0; i--) {
if (parts[i] === '..') {
up++;
} else if (up) {
up--;
} else {
res.push(parts[i]);
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
res.push('..');
}
}
return res.reverse();
}
function trim(arr) {
let start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') { break; }
}
let end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') { break; }
}
return start <= end ? arr.slice(start, end + 1) : [];
}
function normalizeUNCRoot(device) {
return '\\\\' + device.replace(/^[\\\/]+/, '').replace(/[\\\/]+/g, '\\');
}
exports.sep = IS_WINDOWS ? '\\' : '/';
exports.delimiter = IS_WINDOWS ? ';' : ':';
if (IS_WINDOWS) {
// path.resolve([from ...], to)
// windows version
exports.resolve = function resolveWIN32() {
let resolvedDevice = '';
let resolvedTail = '';
let resolvedAbsolute = false;
for (let i = arguments.length - 1; i >= -1; i--) {
let path;
if (i >= 0) {
path = arguments[i];
} else if (!resolvedDevice) {
path = process.cwd();
} else {
// Windows has the concept of drive-specific current working
// directories. If we've resolved a drive letter but not yet an
// absolute path, get cwd for that drive. We're sure the device is not
// an unc path at this points, because unc paths are always absolute.
path = process.env['=' + resolvedDevice];
// Verify that a drive-local cwd was found and that it actually points
// to our drive. If not, default to the drive's root.
if (!path || path.substr(0, 3).toLowerCase() !==
resolvedDevice.toLowerCase() + '\\') {
path = resolvedDevice + '\\';
}
}
// Skip empty and invalid entries
if (!isString(path)) {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
const result = splitDeviceRe.exec(path);
const device = result[1] || '';
const isUnc = device && device.charAt(1) !== ':';
const isAbsolute = exports.isAbsolute(path);
const tail = result[3];
if (device &&
resolvedDevice &&
device.toLowerCase() !== resolvedDevice.toLowerCase()) {
// This path points to another device so it is not applicable
continue;
}
if (!resolvedDevice) {
resolvedDevice = device;
}
if (!resolvedAbsolute) {
resolvedTail = tail + '\\' + resolvedTail;
resolvedAbsolute = isAbsolute;
}
// Convert slashes to backslashes when `resolvedDevice` points to an UNC
// root. Also squash multiple slashes into a single one where appropriate.
if (isUnc) {
resolvedDevice = normalizeUNCRoot(resolvedDevice);
}
if (resolvedDevice && resolvedAbsolute) {
break;
}
}
// At this point the path should be resolved to a full absolute path,
// but handle relative paths to be safe (might happen when process.cwd()
// fails)
// Normalize the tail path
resolvedTail = normalizeArray(
resolvedTail.split(/[\\\/]+/),
!resolvedAbsolute
).join('\\');
return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail)
|| '.';
};
// windows version
exports.normalize = function normalizeWIN32(path) {
const result = splitDeviceRe.exec(path);
let device = result[1] || '';
const isUnc = device && device.charAt(1) !== ':';
const isAbsolute = exports.isAbsolute(path);
let tail = result[3];
const trailingSlash = /[\\\/]$/.test(tail);
// Normalize the tail path
tail = normalizeArray(tail.split(/[\\\/]+/), !isAbsolute).join('\\');
if (!tail && !isAbsolute) {
tail = '.';
}
if (tail && trailingSlash) {
tail += '\\';
}
// Convert slashes to backslashes when `device` points to an UNC root.
// Also squash multiple slashes into a single one where appropriate.
if (isUnc) {
device = normalizeUNCRoot(device);
}
return device + (isAbsolute ? '\\' : '') + tail;
};
// windows version
exports.isAbsolute = function isAbsoluteWIN32(path) {
const result = splitDeviceRe.exec(path);
const device = result[1] || '';
const isUnc = !!device && device.charAt(1) !== ':';
// UNC paths are always absolute
return !!result[2] || isUnc;
};
// windows version
exports.join = function joinWIN32() {
function f(p) {
if (!isString(p)) {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}
const paths = Array.prototype.filter.call(arguments, f);
let joined = paths.join('\\');
// Make sure that the joined path doesn't start with two slashes, because
// normalize() will mistake it for an UNC path then.
//
// This step is skipped when it is very clear that the user actually
// intended to point at an UNC path. This is assumed when the first
// non-empty string arguments starts with exactly two slashes followed by
// at least one more non-slash character.
//
// Note that for normalize() to treat a path as an UNC path it needs to
// have at least 2 components, so we don't filter for that here.
// This means that the user can use join to construct UNC paths from
// a server name and a share name; for example:
// path.join('//server', 'share') -> '\\\\server\\share\')
if (!/^[\\\/]{2}[^\\\/]/.test(paths[0])) {
joined = joined.replace(/^[\\\/]{2,}/, '\\');
}
return exports.normalize(joined);
};
// path.relative(from, to)
// it will solve the relative path from 'from' to 'to', for instance:
// from = 'C:\\orandea\\test\\aaa'
// to = 'C:\\orandea\\impl\\bbb'
// The output of the function should be: '..\\..\\impl\\bbb'
// windows version
exports.relative = function relativeWIN32(from, to) {
from = exports.resolve(from);
to = exports.resolve(to);
// windows is not case sensitive
const lowerFrom = from.toLowerCase();
const lowerTo = to.toLowerCase();
const toParts = trim(to.split('\\'));
const lowerFromParts = trim(lowerFrom.split('\\'));
const lowerToParts = trim(lowerTo.split('\\'));
const length = Math.min(lowerFromParts.length, lowerToParts.length);
let samePartsLength = length;
for (let i = 0; i < length; i++) {
if (lowerFromParts[i] !== lowerToParts[i]) {
samePartsLength = i;
break;
}
}
if (samePartsLength == 0) {
return to;
}
let outputParts = [];
for (let i = samePartsLength; i < lowerFromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('\\');
};
} else /* posix */ {
// path.resolve([from ...], to)
// posix version
exports.resolve = function resolvePOSIX() {
let resolvedPath = '';
let resolvedAbsolute = false;
for (let i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
const path = i >= 0 ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (!isString(path)) {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(
resolvedPath.split('/'),
!resolvedAbsolute
).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function normalizePOSIX(path) {
const isAbsolute = exports.isAbsolute(path);
const trailingSlash = path[path.length - 1] === '/';
// normalize the path
path = normalizeArray(path.split('/'), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function isAbsolutePOSIX(path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function joinPOSIX() {
let path = '';
for (let i = 0; i < arguments.length; i++) {
const segment = arguments[i];
if (!isString(segment)) {
throw new TypeError('Arguments to path.join must be strings');
}
if (segment) {
path += `${path ? '/' : ''}${segment}`;
}
}
return exports.normalize(path);
};
// path.relative(from, to)
// posix version
exports.relative = function relativePOSIX(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
const fromParts = trim(from.split('/'));
const toParts = trim(to.split('/'));
const length = Math.min(fromParts.length, toParts.length);
let samePartsLength = length;
for (let i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
let outputParts = [];
for (let i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
}
exports.exists = util.deprecate(function exists(path, callback) {
return fs.exists(path, callback);
}, 'path.exists is now called `fs.exists`.');
exports.existsSync = util.deprecate(function existsSync(path) {
return fs.existsSync(path);
}, 'path.existsSync is now called `fs.existsSync`.');
if (IS_WINDOWS) {
exports._makeLong = function _makeLongWIN32(path) {
// Note: this will *probably* throw somewhere.
if (!isString(path)) { return path; }
if (!path) { return ''; }
const resolvedPath = exports.resolve(path);
if (/^[a-zA-Z]\:\\/.test(resolvedPath)) {
// path is local filesystem path, which needs to be converted
// to long UNC path.
return '\\\\?\\' + resolvedPath;
} else if (/^\\\\[^?.]/.test(resolvedPath)) {
// path is network UNC path, which needs to be converted
// to long UNC path.
return '\\\\?\\UNC\\' + resolvedPath.substring(2);
}
return path;
};
} else {
exports._makeLong = function _makeLongPOSIX(path) {
return path;
};
}
exports.extname = function _extname(filename) {
if (!filename) { return ''; }
// /a.js///
let end = filename.length;
let c = filename[end - 1];
while (c === exports.sep || c === '/') {
end--;
c = filename[end - 1];
}
let lastDot = -1;
let lastSep = -1;
for (let i = end; i--;) {
const ch = filename[i];
if (lastDot === -1 && ch === '.') {
lastDot = i;
} else if (lastSep === -1 && ch === '/') {
lastSep = i;
} else if (IS_WINDOWS && lastSep === -1 && ch === '\\') {
lastSep = i;
}
// /xxx
if (lastSep !== -1 && lastDot === -1) { return ''; }
// /*.js
if (lastDot !== -1 && i === lastDot - 2) { break; }
// /.js
if (lastSep !== -1 && lastDot !== -1) { break; }
}
// ./js and /.js
if (lastDot < lastSep + 2) { return ''; }
const extname = filename.slice(lastDot, end);
if (extname === '.' && filename[lastDot - 1] === '.') {
// ..
if (lastDot === 1) { return ''; }
const pre = filename[lastDot - 2];
// [//\/]..
if (pre === '/' || pre === exports.sep) { return ''; }
}
return extname;
};
exports.basename = function _basename(filename, ext) {
if (!filename) { return ''; }
// /a.js///
let end = filename.length;
let c = filename[end - 1];
while (c === exports.sep || c === '/') {
end--;
c = filename[end - 1];
}
let lastSep = -1;
for (let i = end; i--;) {
const ch = filename[i];
if (lastSep === -1 && ch === '/') {
lastSep = i;
break;
}
if (IS_WINDOWS && lastSep === -1 && ch === '\\') {
lastSep = i;
break;
}
}
const basename = filename.slice(lastSep + 1, end);
if (ext) {
const match = basename.lastIndexOf(ext);
if (match === -1 || match !== basename.length - ext.length) {
return basename;
}
return basename.slice(0, basename.length - ext.length);
}
return basename;
};
exports.dirname = function _dirname(filename) {
if (!filename) { return '.'; }
let start = 0;
let device = '';
if (IS_WINDOWS) {
// need to get device in windows
device = getDevice(filename);
if (device) { start = device.length; }
}
// /a.js///
let end = filename.length;
let c = filename[end - 1];
while (end >= start && c === exports.sep || c === '/') {
end--;
c = filename[end - 1];
}
let lastSep = -1;
for (let i = end; i-- > start;) {
const ch = filename[i];
if (lastSep === -1 && ch === '/') {
lastSep = i;
break;
}
if (IS_WINDOWS && lastSep === -1 && ch === '\\') {
lastSep = i;
break;
}
}
if (lastSep <= start) {
if (device) { return device; }
if (filename[0] === '/' || filename[0] === exports.sep) { return filename[0]; }
return '.';
}
return device + filename.slice(start, lastSep);
};
exports.replace = function(props) {
if (!props) { props = all; }
if (!Array.isArray(props)) { props = [props]; }
props.forEach(function(name) {
if (exports[name]) { path[name] = exports[name]; }
});
};

View File

@ -9,26 +9,27 @@
'use strict'; 'use strict';
const Cache = require('./Cache'); const Cache = require('./Cache');
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers');
const DeprecatedAssetMap = require('./DependencyGraph/DeprecatedAssetMap');
const Fastfs = require('./fastfs'); const Fastfs = require('./fastfs');
const FileWatcher = require('./FileWatcher'); const FileWatcher = require('./FileWatcher');
const HasteMap = require('./DependencyGraph/HasteMap');
const JestHasteMap = require('jest-haste-map'); const JestHasteMap = require('jest-haste-map');
const Module = require('./Module'); const Module = require('./Module');
const ModuleCache = require('./ModuleCache'); const ModuleCache = require('./ModuleCache');
const Polyfill = require('./Polyfill'); const Polyfill = require('./Polyfill');
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest');
const ResolutionResponse = require('./DependencyGraph/ResolutionResponse');
const extractRequires = require('./lib/extractRequires'); const extractRequires = require('./lib/extractRequires');
const getAssetDataFromName = require('./lib/getAssetDataFromName'); const getAssetDataFromName = require('./lib/getAssetDataFromName');
const getInverseDependencies = require('./lib/getInverseDependencies'); const getInverseDependencies = require('./lib/getInverseDependencies');
const getPlatformExtension = require('./lib/getPlatformExtension'); const getPlatformExtension = require('./lib/getPlatformExtension');
const isAbsolutePath = require('absolute-path'); const isAbsolutePath = require('absolute-path');
const replacePatterns = require('./lib/replacePatterns');
const path = require('./fastpath');
const util = require('util');
const os = require('os'); const os = require('os');
const DependencyGraphHelpers = require('./DependencyGraph/DependencyGraphHelpers'); const path = require('path');
const ResolutionRequest = require('./DependencyGraph/ResolutionRequest'); const replacePatterns = require('./lib/replacePatterns');
const ResolutionResponse = require('./DependencyGraph/ResolutionResponse'); const util = require('util');
const HasteMap = require('./DependencyGraph/HasteMap');
const DeprecatedAssetMap = require('./DependencyGraph/DeprecatedAssetMap');
const ERROR_BUILDING_DEP_GRAPH = 'DependencyGraphError'; const ERROR_BUILDING_DEP_GRAPH = 'DependencyGraphError';

View File

@ -8,8 +8,8 @@
*/ */
'use strict'; 'use strict';
const path = require('../fastpath');
const getPlatformExtension = require('./getPlatformExtension'); const getPlatformExtension = require('./getPlatformExtension');
const path = require('path');
function getAssetDataFromName(filename, platforms) { function getAssetDataFromName(filename, platforms) {
const ext = path.extname(filename); const ext = path.extname(filename);