Browse Source

Minor module-node fixes

* Fix typo in type name (duk_int -> duk_int_t)

* Fix value stack index usage for safe call, was using positive indices

* Add exitcode to test.c so that 'make test' errors out

* Add exitcode to other extras too where applicable
pull/818/head
Sami Vaarala 9 years ago
parent
commit
8f0aaa8413
  1. 7
      extras/console/test.c
  2. 12
      extras/logging/test.c
  3. 23
      extras/module-node/Makefile
  4. 15
      extras/module-node/README.rst
  5. 44
      extras/module-node/duk_module_node.c
  6. 2
      extras/module-node/duk_module_node.h
  7. 31
      extras/module-node/test.c
  8. 7
      extras/print-alert/test.c

7
extras/console/test.c

@ -5,6 +5,7 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
duk_context *ctx; duk_context *ctx;
int i; int i;
int exitcode = 0;
ctx = duk_create_heap_default(); ctx = duk_create_heap_default();
if (!ctx) { if (!ctx) {
@ -16,12 +17,14 @@ int main(int argc, char *argv[]) {
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
printf("Evaling: %s\n", argv[i]); printf("Evaling: %s\n", argv[i]);
(void) duk_peval_string(ctx, argv[i]); if (duk_peval_string(ctx, argv[i]) != 0) {
exitcode = 1;
}
printf("--> %s\n", duk_safe_to_string(ctx, -1)); printf("--> %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx); duk_pop(ctx);
} }
printf("Done\n"); printf("Done\n");
duk_destroy_heap(ctx); duk_destroy_heap(ctx);
return 0; return exitcode;
} }

12
extras/logging/test.c

@ -24,6 +24,7 @@ static duk_ret_t init_logging(duk_context *ctx, void *udata) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
duk_context *ctx; duk_context *ctx;
int i; int i;
int exitcode = 0;
ctx = duk_create_heap_default(); ctx = duk_create_heap_default();
if (!ctx) { if (!ctx) {
@ -38,13 +39,18 @@ int main(int argc, char *argv[]) {
printf("Evaling: %s\n", argv[i]); printf("Evaling: %s\n", argv[i]);
duk_push_string(ctx, argv[i]); duk_push_string(ctx, argv[i]);
duk_push_string(ctx, "evalCodeFileName"); /* for automatic logger name testing */ duk_push_string(ctx, "evalCodeFileName"); /* for automatic logger name testing */
duk_compile(ctx, DUK_COMPILE_EVAL); if (duk_pcompile(ctx, DUK_COMPILE_EVAL) != 0) {
(void) duk_pcall(ctx, 0); exitcode = 1;
} else {
if (duk_pcall(ctx, 0) != 0) {
exitcode = 1;
}
}
printf("--> %s\n", duk_safe_to_string(ctx, -1)); printf("--> %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx); duk_pop(ctx);
} }
printf("Done\n"); printf("Done\n");
duk_destroy_heap(ctx); duk_destroy_heap(ctx);
return 0; return exitcode;
} }

23
extras/module-node/Makefile

@ -2,15 +2,16 @@
.PHONY: test .PHONY: test
test: test:
gcc -o $@ -I../../src/ -I. ../../src/duktape.c duk_module_node.c test.c -lm gcc -Wall -Wextra -std=c99 -o $@ -I../../src/ -I. ../../src/duktape.c duk_module_node.c test.c -lm
@printf '\n' @printf '\n'
./test 'typeof require("pig") === "string" ? "require() OK" : "require() FAILED";' ./test 'assert(typeof require("pig") === "string", "basic require()");'
./test 'require("cow").indexOf("pig") !== -1 ? "nested require() OK" : "nested require() FAILED";' ./test 'assert(require("cow").indexOf("pig") !== -1, "nested require()");'
./test 'var ape1 = require("ape"); var ape2 = require("ape"); ape1 === ape2 ? "caching OK" : "caching FAILED";' ./test 'var ape1 = require("ape"); var ape2 = require("ape"); assert(ape1 === ape2, "caching");'
./test 'var ape1 = require("ape"); var inCache = "ape.js" in require.cache; delete require.cache["ape.js"]; var ape2 = require("ape"); inCache && ape2 !== ape1 ? "require.cache OK" : "require.cache FAILED";' ./test 'var ape1 = require("ape"); var inCache = "ape.js" in require.cache; delete require.cache["ape.js"]; var ape2 = require("ape"); assert(inCache && ape2 !== ape1, "require.cache");'
./test 'var ape = require("ape"); typeof ape.module.require === "function" ? "module.require OK" : "module.require FAILED";' ./test 'var ape = require("ape"); assert(typeof ape.module.require === "function", "module.require()");'
./test 'var ape = require("ape"); ape.module.exports === ape ? "module.exports OK" : "module.exports FAILED";' ./test 'var ape = require("ape"); assert(ape.module.exports === ape, "module.exports");'
./test 'var ape = require("ape"); ape.module.id === "ape.js" && ape.module.id === ape.module.filename ? "module.id OK" : "module.id FAILED";' ./test 'var ape = require("ape"); assert(ape.module.id === "ape.js" && ape.module.id === ape.module.filename, "module.id");'
./test 'var ape = require("ape"); ape.module.filename === "ape.js" ? "module.filename OK" : "module.filename FAILED";' ./test 'var ape = require("ape"); assert(ape.module.filename === "ape.js", "module.filename");'
./test 'var ape = require("ape"); ape.module.loaded === true && ape.wasLoaded === false ? "module.loaded OK" : "module.loaded FAILED";' ./test 'var ape = require("ape"); assert(ape.module.loaded === true && ape.wasLoaded === false, "module.loaded");'
./test 'var ape = require("ape"); ape.__filename === "ape.js" ? "__filename OK" : "__filename FAILED";' ./test 'var ape = require("ape"); assert(ape.__filename === "ape.js", "__filename");'
./test 'var badger = require("badger"); assert(badger.foo === 123 && badger.bar === 234, "exports.foo assignment");'

15
extras/module-node/README.rst

@ -3,7 +3,7 @@ Node.js-like module loading framework
===================================== =====================================
This directory contains an example module resolution and loading framework and This directory contains an example module resolution and loading framework and
``require`` implementation based on the Node.js module system: ``require()`` implementation based on the Node.js module system:
* https://nodejs.org/api/modules.html * https://nodejs.org/api/modules.html
@ -35,9 +35,9 @@ The application needs only to provide the module resolution and loading logic:
It is possible to replace the callbacks after initialization by setting the It is possible to replace the callbacks after initialization by setting the
following internal properties on the global stash: following internal properties on the global stash:
- `\xffmodResolve` - ``\xffmodResolve``
- `\xffmodLoad` - ``\xffmodLoad``
* The resolve callback is a Duktape/C function which takes the string passed * The resolve callback is a Duktape/C function which takes the string passed
to ``require()`` and resolves it to a canonical module ID (for Node.js this to ``require()`` and resolves it to a canonical module ID (for Node.js this
@ -60,11 +60,12 @@ The application needs only to provide the module resolution and loading logic:
If the module ID cannot be resolved, the resolve callback should throw an If the module ID cannot be resolved, the resolve callback should throw an
error, which will propagate out of the ``require()`` call. Note also that error, which will propagate out of the ``require()`` call. Note also that
when the global ``require`` is called, the parent ID is an empty string. when the global ``require()`` is called, the parent ID is an empty string.
* The load callback is a Duktape/C function which takes the resolved module ID * The load callback is a Duktape/C function which takes the resolved module ID
and either returns the Ecmascript source code for the module, or populates and: (1) returns the Ecmascript source code for the module or ``undefined``
``module.exports`` itself and returns undefined (useful for C modules):: if there's no source code, e.g. for pure C modules, (2) can populate
``module.exports`` itself, and (3) can replace ``module.exports``::
duk_ret_t cb_load_module(duk_context *ctx) { duk_ret_t cb_load_module(duk_context *ctx) {
/* /*
@ -80,5 +81,5 @@ The application needs only to provide the module resolution and loading logic:
As with the resolve callback, the load callback should throw an error if the As with the resolve callback, the load callback should throw an error if the
module cannot be loaded for any reason. module cannot be loaded for any reason.
* After these steps, ``require`` will be registered to the global object and * After these steps, ``require()`` will be registered to the global object and
the module system is ready to use. the module system is ready to use.

44
extras/module-node/duk_module_node.c

@ -61,7 +61,6 @@ static duk_ret_t duk__handle_require(duk_context *ctx) {
*/ */
const char *id; const char *id;
duk_ret_t nrets;
const char *parent_id; const char *parent_id;
duk_idx_t module_idx; duk_idx_t module_idx;
duk_idx_t stash_idx; duk_idx_t stash_idx;
@ -73,6 +72,7 @@ static duk_ret_t duk__handle_require(duk_context *ctx) {
duk_push_current_function(ctx); duk_push_current_function(ctx);
(void) duk_get_prop_string(ctx, -1, "\xff" "moduleId"); (void) duk_get_prop_string(ctx, -1, "\xff" "moduleId");
parent_id = duk_require_string(ctx, -1); parent_id = duk_require_string(ctx, -1);
(void) parent_id; /* not used directly; suppress warning */
/* [ id stash require parent_id ] */ /* [ id stash require parent_id ] */
@ -116,7 +116,7 @@ static duk_ret_t duk__handle_require(duk_context *ctx) {
} }
if (duk_is_string(ctx, -1)) { if (duk_is_string(ctx, -1)) {
duk_int ret; duk_int_t ret;
/* [ ... module source ] */ /* [ ... module source ] */
@ -133,7 +133,7 @@ static duk_ret_t duk__handle_require(duk_context *ctx) {
/* nop */ /* nop */
} else { } else {
duk__del_cached_module(ctx, id); duk__del_cached_module(ctx, id);
duk_error(ctx, DUK_ERR_API_ERROR, "error in module load callback"); duk_error(ctx, DUK_ERR_API_ERROR, "invalid module load callback return value");
} }
/* fall through */ /* fall through */
@ -191,7 +191,7 @@ static duk_int_t duk__eval_module_source (duk_context *ctx, void *udata) {
static duk_int_t duk__eval_module_source (duk_context *ctx) { static duk_int_t duk__eval_module_source (duk_context *ctx) {
#endif #endif
/* /*
* Stack: [ module source ] * Stack: [ ... module source ]
*/ */
#if DUK_VERSION >= 19999 #if DUK_VERSION >= 19999
@ -202,36 +202,38 @@ static duk_int_t duk__eval_module_source (duk_context *ctx) {
* way to implement CommonJS closure semantics and matches the behavior of * way to implement CommonJS closure semantics and matches the behavior of
* e.g. Node.js. * e.g. Node.js.
*/ */
duk_push_string(ctx, "(function main(exports, require, module, __filename, __dirname) { "); duk_push_string(ctx, "(function main(exports,require,module,__filename,__dirname){");
duk_dup(ctx, 1); /* source */ duk_dup(ctx, -2); /* source */
duk_push_string(ctx, " })"); duk_push_string(ctx, "})");
duk_concat(ctx, 3); duk_concat(ctx, 3);
/* [ module source func_src ] */ /* [ ... module source func_src ] */
(void) duk_get_prop_string(ctx, 0, "filename"); (void) duk_get_prop_string(ctx, -3, "filename");
duk_compile(ctx, DUK_COMPILE_EVAL); duk_compile(ctx, DUK_COMPILE_EVAL);
duk_call(ctx, 0); duk_call(ctx, 0);
/* [ module source func ] */ /* [ ... module source func ] */
/* call the function wrapper */ /* call the function wrapper */
(void) duk_get_prop_string(ctx, 0, "exports"); /* exports */ (void) duk_get_prop_string(ctx, -3, "exports"); /* exports */
(void) duk_get_prop_string(ctx, 0, "require"); /* require */ (void) duk_get_prop_string(ctx, -4, "require"); /* require */
duk_dup(ctx, 0); /* module */ duk_dup(ctx, -5); /* module */
(void) duk_get_prop_string(ctx, 0, "filename"); /* __filename */ (void) duk_get_prop_string(ctx, -6, "filename"); /* __filename */
duk_push_undefined(ctx); /* __dirname */ duk_push_undefined(ctx); /* __dirname */
duk_call(ctx, 5); duk_call(ctx, 5);
/* [ ... module source result(ignore) ] */
/* module.loaded = true */ /* module.loaded = true */
duk_push_true(ctx); duk_push_true(ctx);
duk_put_prop_string(ctx, 0, "loaded"); duk_put_prop_string(ctx, -4, "loaded");
/* [ module source retval ] */ /* [ ... module source retval ] */
duk_pop_2(ctx); duk_pop_2(ctx);
/* [ module ] */ /* [ ... module ] */
return 1; return 1;
} }
@ -243,16 +245,18 @@ void duk_module_node_init(duk_context *ctx) {
duk_idx_t options_idx; duk_idx_t options_idx;
duk_require_object_coercible(ctx, -1); duk_require_object_coercible(ctx, -1); /* error before setting up requireCache */
options_idx = duk_require_normalize_index(ctx, -1); options_idx = duk_require_normalize_index(ctx, -1);
/* initialize the require cache to a fresh object */ /* Initialize the require cache to a fresh object. */
duk_push_global_stash(ctx); duk_push_global_stash(ctx);
duk_push_object(ctx); duk_push_object(ctx);
duk_put_prop_string(ctx, -2, "\xff" "requireCache"); duk_put_prop_string(ctx, -2, "\xff" "requireCache");
duk_pop(ctx); duk_pop(ctx);
/* stash callbacks for later use */ /* Stash callbacks for later use. User code can overwrite them later
* on directly by accessing the global stash.
*/
duk_push_global_stash(ctx); duk_push_global_stash(ctx);
duk_get_prop_string(ctx, options_idx, "resolve"); duk_get_prop_string(ctx, options_idx, "resolve");
duk_require_function(ctx, -1); duk_require_function(ctx, -1);

2
extras/module-node/duk_module_node.h

@ -3,6 +3,6 @@
#include "duktape.h" #include "duktape.h"
extern void duk_module_node_init (duk_context *ctx); extern void duk_module_node_init(duk_context *ctx);
#endif /* DUK_MODULE_NODE_H_INCLUDED */ #endif /* DUK_MODULE_NODE_H_INCLUDED */

31
extras/module-node/test.c

@ -34,8 +34,10 @@ static duk_ret_t cb_load_module(duk_context *ctx) {
duk_push_string(ctx, "module.exports = require('pig');"); duk_push_string(ctx, "module.exports = require('pig');");
} else if (strcmp(module_id, "ape.js") == 0) { } else if (strcmp(module_id, "ape.js") == 0) {
duk_push_string(ctx, "module.exports = { module: module, __filename: __filename, wasLoaded: module.loaded };"); duk_push_string(ctx, "module.exports = { module: module, __filename: __filename, wasLoaded: module.loaded };");
} else if (strcmp(module_id, "badger.js") == 0) {
duk_push_string(ctx, "exports.foo = 123; exports.bar = 234;");
} else { } else {
duk_push_string(ctx, "module.exports = undefined;"); duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot find module: %s", module_id);
} }
return 1; return 1;
@ -46,15 +48,29 @@ static duk_ret_t handle_print(duk_context *ctx) {
return 0; return 0;
} }
static duk_ret_t handle_assert(duk_context *ctx) {
if (duk_to_boolean(ctx, 0)) {
return 0;
}
duk_error(ctx, DUK_ERR_ERROR, "assertion failed: %s", duk_safe_to_string(ctx, 1));
return 0;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
duk_context *ctx; duk_context *ctx;
int i; int i;
int exitcode = 0;
ctx = duk_create_heap_default(); ctx = duk_create_heap_default();
if (!ctx) { if (!ctx) {
return 1; return 1;
} }
duk_push_c_function(ctx, handle_print, 1);
duk_put_global_string(ctx, "print");
duk_push_c_function(ctx, handle_assert, 2);
duk_put_global_string(ctx, "assert");
duk_push_object(ctx); duk_push_object(ctx);
duk_push_c_function(ctx, cb_resolve_module, DUK_VARARGS); duk_push_c_function(ctx, cb_resolve_module, DUK_VARARGS);
duk_put_prop_string(ctx, -2, "resolve"); duk_put_prop_string(ctx, -2, "resolve");
@ -65,12 +81,19 @@ int main(int argc, char *argv[]) {
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
printf("Evaling: %s\n", argv[i]); printf("Evaling: %s\n", argv[i]);
(void) duk_peval_string(ctx, argv[i]); if (duk_peval_string(ctx, argv[i]) != 0) {
if (duk_get_prop_string(ctx, -1, "stack")) {
duk_replace(ctx, -2);
} else {
duk_pop(ctx);
}
exitcode = 1;
}
printf("--> %s\n", duk_safe_to_string(ctx, -1)); printf("--> %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx); duk_pop(ctx);
} }
printf("Done\n\n"); printf("Done\n");
duk_destroy_heap(ctx); duk_destroy_heap(ctx);
return 0; return exitcode;
} }

7
extras/print-alert/test.c

@ -5,6 +5,7 @@
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
duk_context *ctx; duk_context *ctx;
int i; int i;
int exitcode = 0;
ctx = duk_create_heap_default(); ctx = duk_create_heap_default();
if (!ctx) { if (!ctx) {
@ -16,12 +17,14 @@ int main(int argc, char *argv[]) {
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
printf("Evaling: %s\n", argv[i]); printf("Evaling: %s\n", argv[i]);
(void) duk_peval_string(ctx, argv[i]); if (duk_peval_string(ctx, argv[i]) != 0) {
exitcode = 1;
}
printf("--> %s\n", duk_safe_to_string(ctx, -1)); printf("--> %s\n", duk_safe_to_string(ctx, -1));
duk_pop(ctx); duk_pop(ctx);
} }
printf("Done\n"); printf("Done\n");
duk_destroy_heap(ctx); duk_destroy_heap(ctx);
return 0; return exitcode;
} }

Loading…
Cancel
Save