Skip to content

Jasssonpet/require #673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
path = tests/TestRunner/app/shared
url = [email protected]:NativeScript/common-runtime-tests-app.git
[submodule "common-runtime-tests-modules"]
path = tests/TestRunner/app/tns_modules/shared
path = tests/TestRunner/app/tns_modules/tns-core-modules/shared
url = [email protected]:NativeScript/common-runtime-tests-modules.git
[submodule "src/webkit"]
path = src/webkit
Expand Down
105 changes: 76 additions & 29 deletions src/NativeScript/GlobalObject.moduleLoader.mm
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,55 @@
return nil;
}

static NSString* resolveFile(NSString* filePath) {
if (stat<S_IFREG>(filePath)) {
return filePath;
} else if (NSString* path = stat<S_IFREG>([filePath stringByAppendingPathExtension:@"js"])) {
static NSString* resolveAbsolutePath(NSString* absolutePath, WTF::HashMap<WTF::String, WTF::String, WTF::ASCIICaseInsensitiveHash>& cache, NSError** error) {
if (cache.contains(absolutePath)) {
return cache.get(absolutePath);
}

if (stat<S_IFREG>(absolutePath)) {
cache.set(absolutePath, absolutePath);
return absolutePath;
}

if (NSString* path = stat<S_IFREG>([absolutePath stringByAppendingPathExtension:@"js"])) {
cache.set(absolutePath, path);
return path;
} else if (NSString* path = stat<S_IFREG>([filePath stringByAppendingPathExtension:@"json"])) {
}

if (NSString* path = stat<S_IFREG>([absolutePath stringByAppendingPathExtension:@"json"])) {
cache.set(absolutePath, path);
return path;
}

if (stat<S_IFDIR>(absolutePath)) {
NSString* mainName = @"index.js";

NSString* packageJsonPath = [absolutePath stringByAppendingPathComponent:@"package.json"];
if (stat<S_IFREG>(packageJsonPath)) {
NSData* packageJsonData = [NSData dataWithContentsOfFile:packageJsonPath options:0 error:error];
if (!packageJsonData && error) {
return nil;
}

NSDictionary* packageJson = [NSJSONSerialization JSONObjectWithData:packageJsonData options:0 error:error];
if (!packageJson && error) {
return nil;
}

if (NSString* packageMain = [packageJson objectForKey:@"main"]) {
mainName = packageMain;
}
}

NSString* resolved = resolveAbsolutePath([absolutePath stringByAppendingPathComponent:mainName], cache, error);
if (*error) {
return nil;
}

cache.set(absolutePath, resolved);
return resolved;
}

return nil;
}

Expand All @@ -77,6 +117,9 @@

NSString* absolutePath = path;
unichar pathChar = [path characterAtIndex:0];

bool isModuleRequire = false;

if (pathChar != '/') {
if (pathChar == '.') {
if (referrerValue.isString()) {
Expand All @@ -88,48 +131,52 @@
absolutePath = [static_cast<NSString*>(self->applicationPath()) stringByAppendingPathComponent:@"app"];
path = [path substringFromIndex:2];
} else {
absolutePath = [static_cast<NSString*>(self->applicationPath()) stringByAppendingPathComponent:@"app/tns_modules"];
absolutePath = [static_cast<NSString*>(self->applicationPath()) stringByAppendingPathComponent:@"app/tns_modules/tns-core-modules"];
isModuleRequire = true;
}

absolutePath = [[absolutePath stringByAppendingPathComponent:path] stringByStandardizingPath];
}

WTF::String requestedPath = absolutePath;
if (self->modulePathCache().contains(requestedPath)) {
return deferred->resolve(execState, jsString(execState, self->modulePathCache().get(requestedPath)));
NSError* error = nil;
NSString* absoluteFilePath = resolveAbsolutePath(absolutePath, self->modulePathCache(), &error);
if (error) {
return deferred->reject(execState, self->interop()->wrapError(execState, error));
}

NSString* absoluteFilePath = resolveFile(absolutePath);
if (!absoluteFilePath && stat<S_IFDIR>(absolutePath)) {
NSString* mainFileName = @"index.js";

NSString* packageJsonPath = [absolutePath stringByAppendingPathComponent:@"package.json"];
if (stat<S_IFREG>(packageJsonPath)) {
NSError* error = nil;
NSData* packageJsonData = [NSData dataWithContentsOfFile:packageJsonPath options:0 error:&error];
if (!packageJsonData && error) {
return deferred->reject(execState, self->interop()->wrapError(execState, error));
}

NSDictionary* packageJson = [NSJSONSerialization JSONObjectWithData:packageJsonData options:0 error:&error];
if (!packageJson && error) {
if (isModuleRequire) {
if (!absoluteFilePath) {
absolutePath = [[[static_cast<NSString*>(self->applicationPath()) stringByAppendingPathComponent:@"app/tns_modules"] stringByAppendingPathComponent:path] stringByStandardizingPath];
absoluteFilePath = resolveAbsolutePath(absolutePath, self->modulePathCache(), &error);
if (error) {
return deferred->reject(execState, self->interop()->wrapError(execState, error));
}

if (NSString* packageMain = [packageJson objectForKey:@"main"]) {
mainFileName = packageMain;
}
}

absoluteFilePath = resolveFile([absolutePath stringByAppendingPathComponent:mainFileName]);
if (!absoluteFilePath) {
NSString* currentSearchPath = [static_cast<NSString*>(referrerValue.toWTFString(execState)) stringByDeletingLastPathComponent];
do {
NSString* currentNodeModulesPath = [[currentSearchPath stringByAppendingPathComponent:@"node_modules"] stringByStandardizingPath];
if (stat<S_IFDIR>(currentNodeModulesPath)) {
absoluteFilePath = resolveAbsolutePath([currentNodeModulesPath stringByAppendingPathComponent:path], self->modulePathCache(), &error);
if (error) {
return deferred->reject(execState, self->interop()->wrapError(execState, error));
}

if (absoluteFilePath) {
break;
}
}
currentSearchPath = [currentSearchPath stringByDeletingLastPathComponent];
} while (currentSearchPath.length > self->applicationPath().length());
}
}

if (!absoluteFilePath) {
WTF::String errorMessage = WTF::String::format("Could not find module '%s'. Computed path '%s'.", keyValue.toWTFString(execState).utf8().data(), absolutePath.UTF8String);
return deferred->reject(execState, createError(execState, errorMessage));
}

self->modulePathCache().set(requestedPath, absoluteFilePath);
return deferred->resolve(execState, jsString(execState, absoluteFilePath));
}

Expand Down
10 changes: 10 additions & 0 deletions tests/TestRunner/app/Modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,14 @@ describe(module.id, function () {
it("Windows encoding file", function () {
expect(() => require("./WindowsEncoding")).toThrowError(/character encoding/);
});

// TODO: [2017-04-20] Delete deprecated module search functionality
it("core-module", function () {
require("core-module");
expect(TNSGetOutput()).toBe('core-module loaded');
});
it("core-module-dir", function () {
require("core-module-dir");
expect(TNSGetOutput()).toBe('core-module-dir loaded');
});
});
2 changes: 1 addition & 1 deletion tests/TestRunner/app/shared
Submodule shared updated 21 files
+7 −0 Require/PackageJsonMainPointsToDir/package.json
+2 −0 Require/PackageJsonMainPointsToDir/subdirectory/index.js
+36 −0 Require/index.js
+8 −0 Require/node_modules/CantFindNodeModule/node_modules/SubDependency/node_modules/SubDependency1/index.js
+7 −0 Require/node_modules/CantFindNodeModule/package.json
+3 −0 Require/node_modules/FindInOuterNodeModules/node_modules/SubDependency/node_modules/SubDependency1/index.js
+1 −0 Require/node_modules/FindInOuterNodeModules/node_modules/verySpecifficFileName.js
+7 −0 Require/node_modules/FindInOuterNodeModules/package.json
+7 −0 Require/node_modules/FindsIndexJs/package.json
+1 −0 Require/node_modules/FindsIndexJs/subfolder/node_modules/upperFile.js
+3 −0 Require/node_modules/FindsIndexJs/subfolder/subfolder1/subfolder2/index.js
+3 −0 Require/node_modules/FindsInnerNodeModulesFirst/node_modules/SubDependency/my.js
+1 −0 ...ules/FindsInnerNodeModulesFirst/node_modules/SubDependency/node_modules/FindsInnerNodeModulesFirst/index.js
+1 −0 Require/node_modules/FindsInnerNodeModulesFirst/node_modules/index.js
+7 −0 Require/node_modules/FindsInnerNodeModulesFirst/package.json
+4 −0 Require/node_modules/FindsNativeModulesFirst/index.js
+1 −0 Require/node_modules/FindsNativeModulesFirst/node_modules/shared/Require/RequireModuleFolderConflict/index.js
+7 −0 Require/node_modules/FindsPackageJson/package.json
+1 −0 Require/node_modules/FindsPackageJson/subfolder/node_modules/upperDependency/io.js
+7 −0 Require/node_modules/FindsPackageJson/subfolder/node_modules/upperDependency/package.json
+3 −0 Require/node_modules/FindsPackageJson/subfolder/subfolder1/subfolder2/index.js
1 change: 1 addition & 0 deletions tests/TestRunner/app/tns_modules/core-module-dir/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TNSLog('core-module-dir loaded');
1 change: 1 addition & 0 deletions tests/TestRunner/app/tns_modules/core-module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
TNSLog('core-module loaded');
1 change: 0 additions & 1 deletion tests/TestRunner/app/tns_modules/shared
Submodule shared deleted from b10c9e
1 change: 1 addition & 0 deletions tests/TestRunner/app/tns_modules/tns-core-modules/shared
Submodule shared added at 52e673