Skip to content
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

Add relative file support to emduk using NODEFS #355

Merged
merged 2 commits into from
Sep 17, 2015
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
80 changes: 78 additions & 2 deletions examples/cmdline/duk_cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#include <readline/readline.h>
#include <readline/history.h>
#endif
#if defined(EMSCRIPTEN)
#include <emscripten.h>
#endif
#ifdef DUK_CMDLINE_ALLOC_LOGGING
#include "duk_alloc_logging.h"
#endif
Expand Down Expand Up @@ -183,11 +186,25 @@ static int wrapped_compile_execute(duk_context *ctx) {
void *bc_ptr;
duk_size_t bc_len;
size_t wrote;
char fnbuf[256];
const char *filename;

duk_dup_top(ctx);
duk_dump_function(ctx);
bc_ptr = duk_require_buffer(ctx, -1, &bc_len);
f = fopen(duk_require_string(ctx, -5), "wb");
filename = duk_require_string(ctx, -5);
#if defined(EMSCRIPTEN)
if (filename[0] == '/') {
snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
} else {
snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
}
#else
snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
#endif
fnbuf[sizeof(fnbuf) - 1] = (char) 0;

f = fopen(fnbuf, "wb");
if (!f) {
duk_error(ctx, DUK_ERR_ERROR, "failed to open bytecode output file");
}
Expand Down Expand Up @@ -380,8 +397,20 @@ static int handle_fh(duk_context *ctx, FILE *f, const char *filename, const char
static int handle_file(duk_context *ctx, const char *filename, const char *bytecode_filename) {
FILE *f = NULL;
int retval;
char fnbuf[256];

f = fopen(filename, "rb");
#if defined(EMSCRIPTEN)
if (filename[0] == '/') {
snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
} else {
snprintf(fnbuf, sizeof(fnbuf), "/working/%s", filename);
}
#else
snprintf(fnbuf, sizeof(fnbuf), "%s", filename);
#endif
fnbuf[sizeof(fnbuf) - 1] = (char) 0;

f = fopen(fnbuf, "rb");
if (!f) {
fprintf(stderr, "failed to open source file: %s\n", filename);
fflush(stderr);
Expand Down Expand Up @@ -739,6 +768,53 @@ int main(int argc, char *argv[]) {
const char *compile_filename = NULL;
int i;

#if defined(EMSCRIPTEN)
/* Try to use NODEFS to provide access to local files. Mount the
* CWD as /working, and then prepend "/working/" to relative native
* paths in file calls to get something that works reasonably for
* relative paths. Emscripten doesn't support replacing virtual
* "/" with host "/" (the default MEMFS at "/" can't be unmounted)
* but we can mount "/tmp" as host "/tmp" to allow testcase runs.
*
* https://kripken.github.io/emscripten-site/docs/api_reference/Filesystem-API.html#filesystem-api-nodefs
* /~https://github.com/kripken/emscripten/blob/master/tests/fs/test_nodefs_rw.c
*/
EM_ASM(
/* At the moment it's not possible to replace the default MEMFS mounted at '/':
* /~https://github.com/kripken/emscripten/issues/2040
* /~https://github.com/kripken/emscripten/blob/incoming/src/library_fs.js#L1341-L1358
*/
/*
try {
FS.unmount("/");
} catch (e) {
console.log("Failed to unmount default '/' MEMFS mount: " + e);
}
*/
try {
FS.mkdir("/working");
FS.mount(NODEFS, { root: "." }, "/working");
} catch (e) {
console.log("Failed to mount NODEFS /working: " + e);
}
/* A virtual '/tmp' exists by default:
* https://gist.github.com/evanw/e6be28094f34451bd5bd#file-temp-js-L3806-L3809
*/
/*
try {
FS.mkdir("/tmp");
} catch (e) {
console.log("Failed to create virtual /tmp: " + e);
}
*/
try {
FS.mount(NODEFS, { root: "/tmp" }, "/tmp");
} catch (e) {
console.log("Failed to mount NODEFS /tmp: " + e);
}
);
#endif /* EMSCRIPTEN */

#ifdef DUK_CMDLINE_AJSHEAP
alloc_provider = ALLOC_AJSHEAP;
#endif
Expand Down
15 changes: 15 additions & 0 deletions runtests/runtests.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var optMinifyClosure;
var optMinifyUglifyJS;
var optMinifyUglifyJS2;
var optUtilIncludePath;
var optEmdukTrailingLineHack;
var knownIssues;

/*
Expand Down Expand Up @@ -144,6 +145,14 @@ function executeTest(options, callback) {
function execDone(error, stdout, stderr) {
var res;

// Emduk outputs an extra '\x20\0a' to end of stdout, strip it
if (optEmdukTrailingLineHack &&
typeof stdout === 'string' &&
stdout.length >= 2 &&
stdout.substring(stdout.length - 2) === ' \n') {
stdout = stdout.substring(0, stdout.length - 2);
}

res = {
testcase: options.testcase,
engine: options.engine,
Expand Down Expand Up @@ -467,6 +476,7 @@ function testRunnerMain() {
.boolean('verbose')
.boolean('report-diff-to-other')
.boolean('valgrind')
.boolean('emduk-trailing-line-hack')
.describe('num-threads', 'number of threads to use for testcase execution')
.describe('test-sleep', 'sleep time (milliseconds) between testcases, avoid overheating :)')
.describe('run-duk', 'run testcase with Duktape')
Expand All @@ -486,6 +496,7 @@ function testRunnerMain() {
.describe('minify-uglifyjs', 'path for UglifyJS executable')
.describe('minify-uglifyjs2', 'path for UglifyJS2 executable')
.describe('known-issues', 'known issues yaml file')
.describe('emduk-trailing-line-hack', 'strip bogus newline from end of emduk stdout')
.demand('prep-test-path')
.demand('util-include-path')
.demand(1) // at least 1 non-arg
Expand Down Expand Up @@ -759,6 +770,10 @@ function testRunnerMain() {
knownIssues = yaml.load(argv['known-issues']);
}

if (argv['emduk-trailing-line-hack']) {
optEmdukTrailingLineHack = true;
}

engines = [];
if (argv['run-duk']) {
engines.push({ name: 'duk',
Expand Down