Skip to content

Commit

Permalink
Fixed issue #9
Browse files Browse the repository at this point in the history
Now storing the working directory for each Process in the FileSystem object
instead of relying on uv_chdir and uv_cwd.  Added test case.
  • Loading branch information
Eric Lange authored and Eric Lange committed Jan 9, 2017
1 parent 97e8ef5 commit 9d14ea0
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 116 deletions.
6 changes: 0 additions & 6 deletions .idea/encodings.xml

This file was deleted.

3 changes: 2 additions & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions .idea/inspectionProfiles/Project_Default.xml

This file was deleted.

7 changes: 0 additions & 7 deletions .idea/inspectionProfiles/profiles_settings.xml

This file was deleted.

76 changes: 1 addition & 75 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 20 additions & 11 deletions LiquidCoreAndroid/jni/node/NodeInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,14 @@ void NodeInstance::Chdir(const FunctionCallbackInfo<Value>& args) {

BufferValue path(args.GetIsolate(), nodedroid::fs_(env, args[0], _FS_ACCESS_RD));

// Only using uv_chdir to validate path -- the default path should never be used
int err = uv_chdir(*path);
if (err) {
return env->ThrowUVException(err, "uv_chdir");
}

// The real default path is held in the filesystem object
nodedroid::chdir_(env, args[0]);
}

std::map<Environment*,NodeInstance*> NodeInstance::instance_map;
Expand All @@ -253,19 +257,24 @@ void NodeInstance::Exit(const FunctionCallbackInfo<Value>& args) {

void NodeInstance::Cwd(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
char buf[PATH_MAX];
Local<Value> aliased;

size_t cwd_len = sizeof(buf);
int err = uv_cwd(buf, &cwd_len);
if (err) {
return env->ThrowUVException(err, "uv_cwd");
}
aliased = nodedroid::cwd_(env);
if (aliased->IsUndefined()) {
char buf[PATH_MAX];

Local<String> cwd = String::NewFromUtf8(env->isolate(),
buf,
String::kNormalString,
cwd_len);
Local<Value> aliased = nodedroid::alias_(env, cwd);
size_t cwd_len = sizeof(buf);
int err = uv_cwd(buf, &cwd_len);
if (err) {
return env->ThrowUVException(err, "uv_cwd");
}

Local<String> cwd = String::NewFromUtf8(env->isolate(),
buf,
String::kNormalString,
cwd_len);
aliased = nodedroid::alias_(env, cwd);
}
args.GetReturnValue().Set(aliased);
}

Expand Down
38 changes: 38 additions & 0 deletions LiquidCoreAndroid/jni/node/nodedroid_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,44 @@ Local<Value> alias_(Environment *env, Local<Value> path)
return path;
}

Local<Value> chdir_(Environment *env, Local<Value> path)
{
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());

Local<v8::Private> privateKey = v8::Private::ForApi(env->isolate(),
String::NewFromUtf8(env->isolate(), "__fs"));
Local<Object> globalObj = env->context()->Global();
Maybe<bool> result = globalObj->HasPrivate(env->context(), privateKey);
if (result.IsJust() && result.FromJust()) {
Local<Value> fsVal;
if(globalObj->GetPrivate(env->context(), privateKey).ToLocal(&fsVal)) {
Local<Object> fsObj = fsVal->ToObject(env->context()).ToLocalChecked();
fsObj->Set(env->context(), String::NewFromUtf8(env->isolate(), "cwd"), path);
}
}
return path;
}

Local<Value> cwd_(Environment *env)
{
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());

Local<v8::Private> privateKey = v8::Private::ForApi(env->isolate(),
String::NewFromUtf8(env->isolate(), "__fs"));
Local<Object> globalObj = env->context()->Global();
Maybe<bool> result = globalObj->HasPrivate(env->context(), privateKey);
if (result.IsJust() && result.FromJust()) {
Local<Value> fsVal;
if(globalObj->GetPrivate(env->context(), privateKey).ToLocal(&fsVal)) {
Local<Object> fsObj = fsVal->ToObject(env->context()).ToLocalChecked();
return fsObj->Get(env->context(), String::NewFromUtf8(env->isolate(), "cwd")).ToLocalChecked();
}
}
return Local<Value>::New(env->isolate(),Undefined(env->isolate()));
}

static void Access(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
HandleScope scope(env->isolate());
Expand Down
2 changes: 2 additions & 0 deletions LiquidCoreAndroid/jni/node/nodedroid_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ namespace nodedroid {
void InitFs(v8::Local<v8::Object> target);
v8::Local<v8::Value> alias_(node::Environment *env, v8::Local<v8::Value> path);
v8::Local<v8::Value> fs_(node::Environment *env, v8::Local<v8::Value> path, int req_access);
v8::Local<v8::Value> chdir_(node::Environment *env, v8::Local<v8::Value> path);
v8::Local<v8::Value> cwd_(node::Environment *env);

extern "C" node::node_module fs_module;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
import org.liquidplayer.javascript.JSBaseArray;
import org.liquidplayer.javascript.JSContext;
import org.liquidplayer.javascript.JSObject;
import org.liquidplayer.javascript.JSValue;

import java.io.File;
import java.io.InputStream;
Expand Down Expand Up @@ -186,4 +187,70 @@ public void onDone(JSContext ctx) {

}

/**
* https://github.com/LiquidPlayer/LiquidCore/issues/9
*/
@Test
public void testChdirCwdMultipleProcesses() throws Exception {
final String dir1 = "/home/external/persistent";
final String dir2 = "/home/external/cache";

final String proc1 = "process.chdir('" + dir1 + "');";
final String proc2 = "process.chdir('" + dir2 + "');";

final Semaphore s1 = new Semaphore(0);
final Semaphore s2 = new Semaphore(0);

class Contexts {
JSContext c1;
JSContext c2;
}

final Contexts contexts = new Contexts();

Process p1 = new Process(InstrumentationRegistry.getContext(), "_",
Process.kMediaAccessPermissionsRW, new Process.EventListener() {
@Override
public void onProcessStart(Process process, JSContext context) {
contexts.c1 = context;
process.keepAlive();
s1.release();
}

@Override public void onProcessAboutToExit(Process process, int exitCode) {}
@Override public void onProcessExit(Process process, int exitCode) {}
@Override public void onProcessFailed(Process process, Exception error) {}
});

Process p2 = new Process(InstrumentationRegistry.getContext(), "_",
Process.kMediaAccessPermissionsRW, new Process.EventListener() {
@Override
public void onProcessStart(Process process, JSContext context) {
contexts.c2 = context;
process.keepAlive();
s2.release();
}

@Override public void onProcessAboutToExit(Process process, int exitCode) {}
@Override public void onProcessExit(Process process, int exitCode) {}
@Override public void onProcessFailed(Process process, Exception error) {}
});

s1.acquire();
s2.acquire();

contexts.c1.evaluateScript(proc1);
JSValue v = contexts.c1.evaluateScript("process.cwd()");
assertEquals(dir1, v.toString());

contexts.c2.evaluateScript(proc2);
v = contexts.c2.evaluateScript("process.cwd()");
assertEquals(dir2, v.toString());

v = contexts.c1.evaluateScript("process.cwd()");
assertEquals(dir1, v.toString());

p1.letDie();
p2.letDie();
}
}
26 changes: 17 additions & 9 deletions LiquidCoreAndroid/src/main/java/org/liquidplayer/node/Process.java
Original file line number Diff line number Diff line change
Expand Up @@ -392,16 +392,18 @@ public void finalize() throws Throwable {
* following structure
*
* /
* /cache
* /home
* /external
* /cache
* /home
* /media [if permissions set]
* /Pictures
* /Movies
* /Downloads
* /... (android standard)
* /home/persistent
* /home/cache
* /home/external
* /home/external/persistent
* /home/external/cache
* /home/media
* /home/media/Pictures
* /home/media/Movies
* /home/media/Ringtones
* /home/media/Downloads
* /home/media/...
*
* Everything else will result in a ENOACES (access denied) error
*/
Expand All @@ -419,6 +421,9 @@ private class FileSystem extends JSObject {
@jsexport(attributes = JSPropertyAttributeReadOnly)
private Property<JSFunction> alias;

@jsexport
private Property<String> cwd;

private String realDir(String dir) {
return getContext().evaluateScript(
"(function(){return require('fs').realpathSync('" + dir + "');})()"
Expand Down Expand Up @@ -505,6 +510,8 @@ private void setUp() {
symlink(media, home + "/media");
aliases_.get().property("/home/media", media);
}

cwd.set("/home");
}

private void tearDown() {
Expand Down Expand Up @@ -542,6 +549,7 @@ private void tearDown() {
*/

fs.set(new JSFunction(ctx, "fs", ""+
"if (!file.startsWith('/')) { file = this.cwd+'/'+file; }" +
"try { file = require('path').resolve(file); } catch (e) {}"+
"var access = 0;"+
"for (var p in this.aliases_) {"+
Expand Down

0 comments on commit 9d14ea0

Please sign in to comment.