Savepoint. Lots happened.

parent ec600bce
function (a, b) {
return a[0] - b[0];
}
......@@ -2,6 +2,8 @@ function (args) {
var env = args.environ;
var argv = args.argv;
var modules = args.modules;
var Queues = args.Queues;
var timers = Queues.timers;
if (typeof global === 'undefined') {
(function () {
var global = new Function('return this;')();
......@@ -16,5 +18,10 @@ function (args) {
var result = modules.dir('./src');
result.sort();
modules.print(JSON.stringify(result));
var testme = modules.assert_safe_path('testme.js');
var testme = modules.compile('testme.js');
//modules.print(testme(3, 4));
modules.print(Object.keys(args.modules));
modules.print(args.Queues.timers.length);
return result
}
function (compareFunction, arr, element) {
// Lol. Efficiency could be improved, but this is most obviously correct.
arr.push(item);
arr.sort(compareFunction);
}
function (a, b) {
return a * b;
}
function (timers) {
/**
* Inserts a callback into the timers queue s.t. the timers queue is
* chronologically ordered.
* @param {Number} mstimestamp [description]
* @param {Function} callback [description]
* @return {[type]} [description]
*/
var scheduleCallback = function (mstimestamp, callback) {
orderedInsert(byMstimestampAscending, timers, [mstimestamp, callback]);
}
// Example polyfills for the browser/node functions with their lame argument order
var setTimeout = function (callback, ms) {
scheduleCallback(Date.now() + ms, callback);
}
var callThenReschedule = function (callback, ms) {
return function () {
callback();
setTimeout(callback, ms); // Is this really what ECMAScript does or does it account for drift?
}
}
var setInterval = function (callback, ms) {
scheduleCallback(Date.now() + ms, callThenReschedule(callback));
}
return {
setTimeout: setTimeout,
setInterval: setInterval,
scheduleCallback: scheduleCallback
}
}
shopt -s extglob
cd src
echo "// Autogenerated by the Queen of Hearts, who cut off everyone's head and added a semicolon." > autogenerated.h
echo '#ifndef FILE_WONDERLAND' >> autogenerated.h
echo '#define FILE_WONDERLAND' >> autogenerated.h
echo "" >> autogenerated.h
echo "// Forward declare everything" >> autogenerated.h
head -n1 -q !(main).c **/*.c | sed 's/\s*{$/;/gi' >> autogenerated.h
echo "" >> autogenerated.h
echo "// Include everything" >> autogenerated.h
echo !(main).c **/*.c | xargs -n1 | sed 's/^\(.*\)$/#include "\1"/g' >> autogenerated.h
echo "" >> autogenerated.h
echo '#endif /* !FILE_WONDERLAND */' >> autogenerated.h
cat autogenerated.h
duk_int_t app_assert_safe_path (duk_context *ctx) {
// Safety check filename argument
duk_require_string(ctx, -1);
const char *filename = duk_get_string(ctx, -1);
if (filename[0] == '\0') {
return duk_error(ctx, DUK_ERR_ERROR, "Path cannot be empty.");
} else if (filename[0] == '/') {
return duk_error(ctx, DUK_ERR_ERROR, "Path should not start with '/' to reference the root directory: %s", filename);
} else if (strstr(filename, "../") != NULL) {
return duk_error(ctx, DUK_ERR_ERROR, "Path should not contain '..' to reference parent directories: %s", filename);
} else if (filename[0] == '.') {
// (this restriction isn't about safety, just consistancy and KISS)
return duk_error(ctx, DUK_ERR_ERROR, "Path should not start with '.' to reference the current directory: %s", filename);
} else if (strstr(filename, "\\") != NULL) {
// No paths with non-standard file separators.
return duk_error(ctx, DUK_ERR_ERROR, "Path should not contain '\\' character, only use '/' to separate paths: %s", filename);
} else {
// Whew! By this point, I think we're only left with canonical representations.
return 0; // 0 results on stack
}
}
int app_push_trusted_function (duk_context *ctx) {
// Safety check filename argument
app_assert_safe_path(ctx);
const char *filename = duk_get_string(ctx, -1);
// Get the fileName property of the calling function.
duk_inspect_callstack_entry(ctx, -2);
// int check = duk_has_prop_string(ctx, -1, "function");
duk_get_prop_string(ctx, -1, "function");
// check = duk_has_prop_string(ctx, -1, "fileName");
duk_get_prop_string(ctx, -1, "fileName");
const char *baseFilename = duk_get_string(ctx, -1);
char *joined_path = c_join_paths(baseFilename, filename);
// Replace with absolute filename
duk_pop(ctx);
duk_push_string(ctx, joined_path);
// Open the file
FILE * pFile = fopen(joined_path, "rb");
if (pFile == NULL) {
return duk_error(ctx, DUK_ERR_ERROR, "could not open file: %s", joined_path);
}
// Get file size http://www.cplusplus.com/reference/cstdio/fread/
fseek(pFile, 0, SEEK_END);
long fileSize = ftell(pFile);
rewind(pFile);
// Allocate a buffer the write size
char * buffer = (char*) malloc (sizeof(char) * fileSize);
if (buffer == NULL) {
return duk_error(ctx, DUK_ERR_ERROR, "could not allocate memory: needed %d bytes to read %s", fileSize, joined_path);
}
// Dump file into memory
size_t bytesRead = fread(buffer, 1, fileSize, pFile);
if (bytesRead != fileSize) {
return duk_error(ctx, DUK_ERR_ERROR, "failed reading file: %s", joined_path);
}
// Close the file bc we're done with it
fclose(pFile);
// Create a function from the file buffer. Leaves it on the stack.
duk_compile_lstring_filename(ctx, DUK_COMPILE_FUNCTION + DUK_COMPILE_STRICT, buffer, bytesRead);
free(buffer);
return 1;
}
// Autogenerated by the Queen of Hearts, who cut off everyone's head and added a semicolon.
#ifndef FILE_WONDERLAND
#define FILE_WONDERLAND
// Forward declare everything
duk_int_t app_assert_safe_path (duk_context *ctx);
int app_push_argv(duk_context *ctx, int argc, char *argv[]);
int app_push_dir (duk_context *ctx);
int app_push_environ(duk_context *ctx);
int app_push_trusted_function (duk_context *ctx);
void app_stash_global_string(duk_context *ctx, char *name);
void app_unstash_global_string(duk_context *ctx, char *name);
char* c_join_paths(const char *base, const char *filename);
int native_import (duk_context *ctx, char * filename);
static duk_ret_t native_print(duk_context *ctx);
int queue_create(duk_context *ctx, char *name);
int queue_push_queue(duk_context *ctx, char *name);
// Include everything
#include "app_assert_safe_path.c"
#include "app_push_argv.c"
#include "app_push_dir.c"
#include "app_push_environ.c"
#include "app_push_trusted_function.c"
#include "app_stash_global_string.c"
#include "app_unstash_global_string.c"
#include "c_join_paths.c"
#include "native_import.c"
#include "native_print.c"
#include "queue/queue_create.c"
#include "queue/queue_push_queue.c"
#endif /* !FILE_WONDERLAND */
char* c_join_paths(const char *base, const char *filename) {
int base_len = strlen(base);
int filename_len = strlen(filename);
char *joined_path = malloc(base_len + filename_len + 5); // 2 for the nulls, 1 for the path separator, 2 more for luck.
strcpy(joined_path, base);
dirname(joined_path); // should shorten if anything
strcat(joined_path, "/");
strcat(joined_path, filename);
return joined_path;
}
// this line intentionally left blank.
// Define externs
extern char **environ;
// Include dependencies
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <libgen.h>
#include <string.h>
#ifdef _WIN32
// @see [1]
#include <io.h>
......@@ -12,14 +17,8 @@ extern char **environ;
#include <omp.h>
#include "duktape.h"
// Include helper functions
#include "app_push_argv.c"
#include "app_push_environ.c"
#include "app_push_dir.c"
#include "native_print.c"
#include "native_import.c"
#include "app_stash_global_string.c"
#include "app_unstash_global_string.c"
// Include all our functions
#include "autogenerated.h"
int main(int argc, char *argv[] /* char *environ[] */) {
// Re-open stdin and stdout in binary mode
......@@ -49,6 +48,9 @@ int main(int argc, char *argv[] /* char *environ[] */) {
duk_push_undefined(ctx);
duk_put_global_string(ctx, "Duktape");
// Create a global (techinically heap-level) event queue
queue_create(ctx, "timers");
// Creat a 2nd JS thread (yes, it's possible in Duktape!)
duk_push_thread(ctx); // TODO: Use duk_push_thread_new_globalenv for modules?
duk_context *ctx2 = duk_get_context(ctx, -1);
......@@ -76,7 +78,16 @@ int main(int argc, char *argv[] /* char *environ[] */) {
duk_put_prop_string(ctx, -2, "print");
app_unstash_global_string(ctx, "Duktape"); // summon from the magic stash
duk_put_prop_string(ctx, -2, "Duktape");
duk_push_c_function(ctx, app_push_trusted_function, 1);
duk_put_prop_string(ctx, -2, "compile");
duk_push_c_function(ctx, app_assert_safe_path, 1);
duk_put_prop_string(ctx, -2, "assert_safe_path");
duk_put_prop_string(ctx, -2, "modules");
// Provide direct access to the event loop
duk_push_object(ctx);
queue_push_queue(ctx, "timers");
duk_put_prop_string(ctx, -2, "timers");
duk_put_prop_string(ctx, -2, "Queues");
// Run top-level module, passing the god arg as the sole argument.
ret = duk_pcall(ctx, 1);
......@@ -89,6 +100,19 @@ int main(int argc, char *argv[] /* char *environ[] */) {
// printf("%s\n", duk_to_string(ctx, -1));
// }
// Now trigger SOME of the event callbacks but not all
if (omp_get_thread_num() % 2) {
queue_push_queue(ctx, "timers");
duk_get_prop_index(ctx, -1, 0);
duk_remove(ctx, -2);
ret = duk_pcall(ctx, 0);
if (ret != 0) {
fprintf(stderr, "%s %s\n", argv[1], duk_safe_to_string(ctx, -1));
goto finally;
}
}
// Load top-level function module
ret = native_import(ctx2, argv[1]);
if (ret != 0) {
......@@ -113,6 +137,11 @@ int main(int argc, char *argv[] /* char *environ[] */) {
duk_get_global_string(ctx2, "Duktape");
duk_put_prop_string(ctx2, -2, "Duktape");
duk_put_prop_string(ctx2, -2, "modules");
// Provide direct access to the event loop
duk_push_object(ctx2);
queue_push_queue(ctx2, "timers");
duk_put_prop_string(ctx2, -2, "timers");
duk_put_prop_string(ctx2, -2, "Queues");
// Run top-level module, passing the god arg as the sole argument.
ret = duk_pcall(ctx2, 1);
......
int queue_create(duk_context *ctx, char *name) {
// Create a top-level Array on the heap stash with the given name
duk_push_heap_stash(ctx);
duk_push_array(ctx);
duk_put_prop_string(ctx, -2, name);
duk_pop(ctx);
return 0;
}
int queue_push_queue(duk_context *ctx, char *name) {
duk_push_heap_stash(ctx);
duk_get_prop_string(ctx, -1, name);
duk_remove(ctx, -2);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment