static const char * get_filename(duk_context *ctx, int index, const es_context_t *ec, int for_write) { const char *filename = duk_to_string(ctx, index); if(gconf.bypass_ecmascript_acl) return filename; if(for_write && ec->ec_bypass_file_acl_write) return filename; if(!for_write && ec->ec_bypass_file_acl_read) return filename; if(strstr(filename, "../") || strstr(filename, "/..")) duk_error(ctx, DUK_ERR_ERROR, "Bad filename %s -- Contains parent references", filename); if((ec->ec_storage != NULL && mystrbegins(filename, ec->ec_storage)) || (ec->ec_path != NULL && mystrbegins(filename, ec->ec_path))) return filename; duk_error(ctx, DUK_ERR_ERROR, "Bad filename %s -- Access not allowed", filename); }
// Load a duktape C function from a shared library by path and name. static duk_ret_t duv_loadlib(duk_context *ctx) { const char *name, *path; uv_lib_t lib; duk_c_function fn; // Check the args const duv_schema_entry schema[] = { { "path", duk_is_string }, { "name", duk_is_string }, { NULL, NULL } }; dschema_check(ctx, schema); path = duk_get_string(ctx, 0); name = duk_get_string(ctx, 1); if (uv_dlopen(path, &lib)) { duk_error(ctx, DUK_ERR_ERROR, "Cannot load shared library %s", path); return 0; } if (uv_dlsym(&lib, name, (void**)&fn)) { duk_error(ctx, DUK_ERR_ERROR, "Unable to find %s in %s", name, path); return 0; } duk_push_c_function(ctx, fn, 0); return 1; }
/** * fd, buffer, offset, length, position */ static int es_file_read(duk_context *ctx) { es_fd_t *efd = es_fd_get(ctx, 0); duk_size_t bufsize; char *buf = duk_require_buffer_data(ctx, 1, &bufsize); const int offset = duk_to_int(ctx, 2); const int len = duk_to_int(ctx, 3); if(offset + len > bufsize) duk_error(ctx, DUK_ERR_ERROR, "Buffer too small %zd < %d + %d", bufsize, offset + len); if(!duk_is_null(ctx, 4)) { // Seek fa_seek(efd->efd_fh, duk_require_number(ctx, 4), SEEK_SET); } int r = fa_read(efd->efd_fh, buf + offset, len); if(r < 0) duk_error(ctx, DUK_ERR_ERROR, "Read error from '%s'", efd->efd_path); duk_push_int(ctx, r); return 1; }
/* * Returns the pid id for a pin object. Also checks that the pin supports the requested function. */ static uint32_t GetPinId(duk_context* ctx, int idx, uint32_t function) { uint32_t id; if (!duk_is_object(ctx, idx)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Requires a pin object"); } /* * Get pin id */ duk_get_prop_string(ctx, idx, "id"); id = duk_require_int(ctx, -1); duk_pop(ctx); /* * Check that the required I/O function is supported */ if (function) { const AJS_IO_Info* info = AJS_TargetIO_GetInfo(id); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", id); return 0; } if (!(info->functions & function)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "I/O function %s not supported on pin%d", AJS_IO_FunctionName(function), id); } } return id; }
static int es_sqlite_create(duk_context *ctx) { char path[PATH_MAX]; char errbuf[512]; es_context_t *ec = es_get(ctx); const char *name = duk_safe_to_string(ctx, 0); // Create the db-dir for this plugin snprintf(path, sizeof(path), "%s/databases", ec->ec_storage); if(fa_makedirs(path, errbuf, sizeof(errbuf))) duk_error(ctx, DUK_ERR_ERROR, "Unable to create directory %s -- %s", path, errbuf); snprintf(path, sizeof(path), "%s/databases/%s", ec->ec_storage, name); sqlite3 *db = db_open(path, 0); if(db == NULL) duk_error(ctx, DUK_ERR_ERROR, "Unable to open database -- check logs"); es_sqlite_t *es = es_resource_create(ec, &es_resource_sqlite, 0); es->es_db = db; es->es_name = strdup(name); es_resource_push(ctx, &es->super); return 1; }
void * es_get_native_obj(duk_context *ctx, int obj_idx, es_native_type_t wanted_type) { duk_get_finalizer(ctx, obj_idx); if(!duk_is_function(ctx, -1)) { duk_error(ctx, DUK_ERR_ERROR, "Object is not of type %s (no finalizer)", native_type_to_str(wanted_type)); } es_native_type_t current_type = duk_get_magic(ctx, -1); duk_pop(ctx); if(current_type != wanted_type) duk_error(ctx, DUK_ERR_ERROR, "Object is %s, expected %s", native_type_to_str(current_type), native_type_to_str(wanted_type)); duk_get_prop_string(ctx, obj_idx, PTRNAME); if(!duk_is_pointer(ctx, -1)) duk_error(ctx, DUK_ERR_ERROR, "Object missing ptr"); void *r = duk_get_pointer(ctx, -1); duk_pop(ctx); return r; }
static int NativePWM(duk_context* ctx) { AJ_Status status; double dutyCycle = duk_require_number(ctx, 0); uint32_t freq = 0; if (dutyCycle > 1.0 || dutyCycle < 0.0) { duk_error(ctx, DUK_ERR_RANGE_ERROR, "Duty cycle must be in the range 0.0 to 1.0"); } /* * Frequency is optional. If not specified zero is passed into the target code and the default * target PWM frequency is used. */ if (!duk_is_undefined(ctx, 1)) { freq = duk_require_int(ctx, 1); if (freq == 0) { duk_error(ctx, DUK_ERR_RANGE_ERROR, "Frequency cannot be zero Hz"); } } status = AJS_TargetIO_PinPWM(PinCtxPtr(ctx), dutyCycle, freq); if (status != AJ_OK) { if (status == AJ_ERR_RESOURCES) { duk_error(ctx, DUK_ERR_RANGE_ERROR, "Too many PWM pins"); } else { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Error setting PWM %s", AJ_StatusText(status)); } } return 0; }
static int NativeIoSpi(duk_context* ctx) { uint32_t mosi, miso, cs, clk, clock; uint8_t master; uint8_t cpol, cpha, data; void* spiCtx; AJ_Status status; int idx; mosi = GetPinId(ctx, 0, AJS_IO_FUNCTION_SPI_MOSI); miso = GetPinId(ctx, 1, AJS_IO_FUNCTION_SPI_MISO); cs = GetPinId(ctx, 2, AJS_IO_FUNCTION_SPI_SS); clk = GetPinId(ctx, 3, AJS_IO_FUNCTION_SPI_SCK); duk_get_prop_string(ctx, 4, "clock"); clock = duk_require_int(ctx, -1); duk_get_prop_string(ctx, 4, "master"); if (duk_get_boolean(ctx, -1)) { master = TRUE; } else { master = FALSE; } duk_get_prop_string(ctx, 4, "cpol"); cpol = duk_require_int(ctx, -1); duk_get_prop_string(ctx, 4, "cpha"); cpha = duk_require_int(ctx, -1); duk_get_prop_string(ctx, 4, "data"); data = duk_require_int(ctx, -1); duk_pop(ctx); // Clock polarity must be high (1) or low (0) if (cpol != 0 && cpol != 1) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "cpol must be 0 or 1; you gave %u", cpol); } // Clock edge phase must be one edge (0) or two edge (1) if (cpha != 0 && cpha != 1) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "cpha must be 0 or 1; you gave %u", cpha); } // Data bits must be 8, 16, or 32 if (data != 8 && data != 16 && data != 32) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "data bits must be 8, 16 or 32; you gave %u", data); } status = AJS_TargetIO_SpiOpen(mosi, miso, cs, clk, clock, master, cpol, cpha, data, &spiCtx); if (status != AJ_OK) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Failed to open SPI device"); } idx = NewIOObject(ctx, spiCtx, AJS_IO_FUNCTION_SPI, NativeSpiFinalizer); duk_push_c_lightfunc(ctx, NativeSpiRead, 1, 0, 0); duk_put_prop_string(ctx, idx, "read"); duk_push_c_lightfunc(ctx, NativeSpiWrite, 1, 0, 0); duk_put_prop_string(ctx, idx, "write"); return 1; }
/* * Looks for an interface that defines a specific member. * * TODO - check for ambiguity - same member defined on multiple interfaces */ static const char* FindInterfaceForMember(duk_context* ctx, duk_idx_t mbrIdx, const char** member) { const char* iface = NULL; uint8_t found = FALSE; size_t numInterfaces; duk_idx_t listIdx; duk_get_prop_string(ctx, -1, "interfaces"); numInterfaces = duk_get_length(ctx, -1); listIdx = AJS_GetAllJoynProperty(ctx, "interfaceDefinition"); if (duk_is_object(ctx, mbrIdx)) { /* * Expect an object of form { member:"org.foo.interface" } */ duk_enum(ctx, mbrIdx, DUK_ENUM_OWN_PROPERTIES_ONLY); if (!duk_next(ctx, -1, 1)) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Require object of form { 'member-name':'interface-name' }"); } iface = duk_require_string(ctx, -1); if (!AJ_StringFindFirstOf(iface, ".") == -1) { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Interface name '%s' is not a dotted name", iface); } *member = duk_require_string(ctx, -2); duk_get_prop_string(ctx, listIdx, iface); if (duk_is_undefined(ctx, -1)) { duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown interface: '%s'", iface); } found = duk_has_prop_string(ctx, -1, *member); duk_pop_n(ctx, 4); } else { size_t i; /* * Expect a string */ *member = duk_require_string(ctx, mbrIdx); for (i = 0; !found && (i < numInterfaces); ++i) { duk_get_prop_index(ctx, -2, i); iface = duk_require_string(ctx, -1); duk_get_prop_string(ctx, listIdx, iface); /* * See if the requested member exists on this interface */ found = duk_has_prop_string(ctx, -1, *member); duk_pop_2(ctx); } } duk_pop_2(ctx); if (!found) { duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown member: '%s'", *member); } return iface; }
static int es_route_create(duk_context *ctx) { const char *str = duk_safe_to_string(ctx, 0); if(str[0] != '^') { int l = strlen(str); char *s = alloca(l + 2); s[0] = '^'; memcpy(s+1, str, l+1); str = s; } es_context_t *ec = es_get(ctx); hts_mutex_lock(&route_mutex); es_route_t *er; LIST_FOREACH(er, &routes, er_link) if(!strcmp(er->er_pattern, str)) break; if(er != NULL) { hts_mutex_unlock(&route_mutex); duk_error(ctx, DUK_ERR_ERROR, "Route %s already exist", str); } er = es_resource_alloc(&es_resource_route); if(hts_regcomp(&er->er_regex, str)) { hts_mutex_unlock(&route_mutex); free(er); duk_error(ctx, DUK_ERR_ERROR, "Invalid regular expression for route %s", str); } er->er_pattern = strdup(str); er->er_prio = strcspn(str, "()[].*?+$") ?: INT32_MAX; LIST_INSERT_SORTED(&routes, er, er_link, er_cmp, es_route_t); es_resource_link(&er->super, ec, 1); hts_mutex_unlock(&route_mutex); es_root_register(ctx, 1, er); es_resource_push(ctx, &er->super); return 1; }
void dschema_check(duk_context *ctx, const duv_schema_entry schema[]) { int i; int top = duk_get_top(ctx); for (i = 0; schema[i].name; ++i) { // printf("Checking arg %d-%s\n", i, schema[i].name); if (schema[i].checker(ctx, i)) continue; duk_dump_context_stderr(ctx); duk_error(ctx, DUK_ERR_TYPE_ERROR, "Invalid argument type for %s", schema[i].name); } if (top > i) { duk_dump_context_stderr(ctx); duk_error(ctx, DUK_ERR_TYPE_ERROR, "Too many arguments. Expected at %d, but got %d", i, top); } }
/* * Serializes various data types into a buffer. Leaves the buffer on the top of the stack. */ static uint8_t* SerializeToBuffer(duk_context* ctx, duk_idx_t idx, duk_size_t* sz) { uint8_t* ptr; switch (duk_get_type(ctx, idx)) { case DUK_TYPE_BUFFER: duk_dup(ctx, idx); ptr = duk_get_buffer(ctx, -1, sz); break; case DUK_TYPE_BOOLEAN: ptr = duk_push_fixed_buffer(ctx, 1); ptr[0] = duk_get_boolean(ctx, idx); *sz = 1; break; case DUK_TYPE_NUMBER: ptr = duk_push_fixed_buffer(ctx, 1); ptr[0] = duk_get_int(ctx, idx); *sz = 1; break; case DUK_TYPE_STRING: duk_dup(ctx, idx); ptr = duk_to_fixed_buffer(ctx, -1, sz); break; case DUK_TYPE_OBJECT: if (duk_is_array(ctx, idx)) { duk_idx_t i; duk_idx_t len = duk_get_length(ctx, idx); ptr = duk_push_fixed_buffer(ctx, len); for (i = 0; i < len; ++i) { duk_get_prop_index(ctx, idx, i); ptr[i] = duk_require_uint(ctx, -1); duk_pop(ctx); } *sz = len; } else { duk_error(ctx, DUK_ERR_TYPE_ERROR, "Can only serialize arrays of numbers"); } break; default: duk_error(ctx, DUK_ERR_TYPE_ERROR, "Cannot serialize"); break; } return ptr; }
static duk_ret_t duk_pmem(duk_context* duk) { tic_machine* machine = getDukMachine(duk); tic_mem* memory = &machine->memory; u32 index = duk_to_int(duk, 0); if(index < TIC_PERSISTENT_SIZE) { u32 val = memory->persistent.data[index]; if(!duk_is_null_or_undefined(duk, 1)) { memory->persistent.data[index] = duk_to_uint(duk, 1); machine->data->syncPMEM = true; } duk_push_int(duk, val); return 1; } else return duk_error(duk, DUK_ERR_ERROR, "invalid persistent memory index\n"); return 0; }
static s32 duk_keyp(duk_context* duk) { tic_machine* machine = getDukMachine(duk); tic_mem* tic = &machine->memory; if (duk_is_null_or_undefined(duk, 0)) { duk_push_boolean(duk, tic->api.keyp(tic, tic_key_unknown, -1, -1)); } else { tic_key key = duk_to_int(duk, 0); if(key >= tic_key_escape) { return duk_error(duk, DUK_ERR_ERROR, "unknown keyboard code\n"); } else { if(duk_is_null_or_undefined(duk, 1) && duk_is_null_or_undefined(duk, 2)) { duk_push_boolean(duk, tic->api.keyp(tic, key, -1, -1)); } else { u32 hold = duk_to_int(duk, 1); u32 period = duk_to_int(duk, 2); duk_push_boolean(duk, tic->api.keyp(tic, key, hold, period)); } } } return 1; }
// Sync readfile using libuv APIs as an API function. static duk_ret_t duv_loadfile(duk_context *ctx) { const char* path = duk_require_string(ctx, 0); uv_fs_t req; int fd = 0; uint64_t size; char* chunk; uv_buf_t buf; if (uv_fs_open(&loop, &req, path, O_RDONLY, 0644, NULL) < 0) goto fail; fd = req.result; if (uv_fs_fstat(&loop, &req, fd, NULL) < 0) goto fail; size = req.statbuf.st_size; chunk = duk_alloc(ctx, size); buf = uv_buf_init(chunk, size); if (uv_fs_read(&loop, &req, fd, &buf, 1, 0, NULL) < 0) goto fail; duk_push_lstring(ctx, chunk, size); duk_free(ctx, chunk); uv_fs_close(&loop, &req, fd, NULL); uv_fs_req_cleanup(&req); return 1; fail: if (fd) uv_fs_close(&loop, &req, fd, NULL); uv_fs_req_cleanup(&req); duk_error(ctx, DUK_ERR_ERROR, "%s: %s: %s", uv_err_name(req.result), uv_strerror(req.result), path); }
static duk_ret_t Line_ClosestPoint_Selector(duk_context* ctx) { int numArgs = duk_get_top(ctx); if (numArgs == 3 && GetValueObject<Ray>(ctx, 0, Ray_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_ClosestPoint_Ray_float_float(ctx); if (numArgs == 3 && GetValueObject<Line>(ctx, 0, Line_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_ClosestPoint_Line_float_float(ctx); if (numArgs == 3 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_ClosestPoint_LineSegment_float_float(ctx); if (numArgs == 3 && GetValueObject<Triangle>(ctx, 0, Triangle_ID) && duk_is_number(ctx, 1) && GetValueObject<float2>(ctx, 2, float2_ID)) return Line_ClosestPoint_Triangle_float_float2(ctx); if (numArgs == 2 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID) && duk_is_number(ctx, 1)) return Line_ClosestPoint_LineSegment_float(ctx); if (numArgs == 2 && GetValueObject<Triangle>(ctx, 0, Triangle_ID) && duk_is_number(ctx, 1)) return Line_ClosestPoint_Triangle_float(ctx); if (numArgs == 2 && GetValueObject<Line>(ctx, 0, Line_ID) && duk_is_number(ctx, 1)) return Line_ClosestPoint_Line_float(ctx); if (numArgs == 2 && GetValueObject<Ray>(ctx, 0, Ray_ID) && duk_is_number(ctx, 1)) return Line_ClosestPoint_Ray_float(ctx); if (numArgs == 2 && GetValueObject<float3>(ctx, 0, float3_ID) && duk_is_number(ctx, 1)) return Line_ClosestPoint_float3_float(ctx); if (numArgs == 1 && GetValueObject<Triangle>(ctx, 0, Triangle_ID)) return Line_ClosestPoint_Triangle(ctx); if (numArgs == 1 && GetValueObject<float3>(ctx, 0, float3_ID)) return Line_ClosestPoint_float3(ctx); if (numArgs == 1 && GetValueObject<Line>(ctx, 0, Line_ID)) return Line_ClosestPoint_Line(ctx); if (numArgs == 1 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID)) return Line_ClosestPoint_LineSegment(ctx); if (numArgs == 1 && GetValueObject<Ray>(ctx, 0, Ray_ID)) return Line_ClosestPoint_Ray(ctx); duk_error(ctx, DUK_ERR_ERROR, "Could not select function overload"); }
static duk_ret_t Line_Distance_Selector(duk_context* ctx) { int numArgs = duk_get_top(ctx); if (numArgs == 3 && GetValueObject<Line>(ctx, 0, Line_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_Distance_Line_float_float(ctx); if (numArgs == 3 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_Distance_LineSegment_float_float(ctx); if (numArgs == 3 && GetValueObject<Ray>(ctx, 0, Ray_ID) && duk_is_number(ctx, 1) && duk_is_number(ctx, 2)) return Line_Distance_Ray_float_float(ctx); if (numArgs == 2 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID) && duk_is_number(ctx, 1)) return Line_Distance_LineSegment_float(ctx); if (numArgs == 2 && GetValueObject<Line>(ctx, 0, Line_ID) && duk_is_number(ctx, 1)) return Line_Distance_Line_float(ctx); if (numArgs == 2 && GetValueObject<float3>(ctx, 0, float3_ID) && duk_is_number(ctx, 1)) return Line_Distance_float3_float(ctx); if (numArgs == 2 && GetValueObject<Ray>(ctx, 0, Ray_ID) && duk_is_number(ctx, 1)) return Line_Distance_Ray_float(ctx); if (numArgs == 1 && GetValueObject<Sphere>(ctx, 0, Sphere_ID)) return Line_Distance_Sphere(ctx); if (numArgs == 1 && GetValueObject<Capsule>(ctx, 0, Capsule_ID)) return Line_Distance_Capsule(ctx); if (numArgs == 1 && GetValueObject<Line>(ctx, 0, Line_ID)) return Line_Distance_Line(ctx); if (numArgs == 1 && GetValueObject<Ray>(ctx, 0, Ray_ID)) return Line_Distance_Ray(ctx); if (numArgs == 1 && GetValueObject<LineSegment>(ctx, 0, LineSegment_ID)) return Line_Distance_LineSegment(ctx); if (numArgs == 1 && GetValueObject<float3>(ctx, 0, float3_ID)) return Line_Distance_float3(ctx); duk_error(ctx, DUK_ERR_ERROR, "Could not select function overload"); }
/*----------------------------------------------------------------------------*/ static duk_ret_t kbjs_sleep(duk_context *context) { /* Check if first argument is a number */ /* STACK: [..., interval] */ if (duk_is_nan(context, (duk_idx_t)-1)) duk_error(context, (duk_errcode_t)kbjs_ArgumentTypeError, kbjs_Error_fmt(kbjs_ArgumentTypeError), SLEEP_FUNC_NAME, "Number", 0, duk_safe_to_string(context, (duk_idx_t)-1)); /* Get first argument as integer in miliseconds */ long ms = (long)floor(fabs(duk_get_number(context, (duk_idx_t)-1))); long s = ms / S_TO_MS; /* Sleep this thread */ struct timespec interval = { (time_t)s, (ms - s*S_TO_MS)*MS_TO_NS }; nanosleep(&interval, NULL); return (duk_ret_t)0; }
static duk_ret_t cb_load_module(duk_context *ctx) { const char *filename; const char *module_id; module_id = duk_require_string(ctx, 0); duk_get_prop_string(ctx, 2, "filename"); filename = duk_require_string(ctx, -1); printf("load_cb: id:'%s', filename:'%s'\n", module_id, filename); if (strcmp(module_id, "pig.js") == 0) { duk_push_sprintf(ctx, "module.exports = 'you\\'re about to get eaten by %s';", module_id); } else if (strcmp(module_id, "cow.js") == 0) { duk_push_string(ctx, "module.exports = require('pig');"); } else if (strcmp(module_id, "ape.js") == 0) { 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 if (strcmp(module_id, "comment.js") == 0) { duk_push_string(ctx, "exports.foo = 123; exports.bar = 234; // comment"); } else if (strcmp(module_id, "shebang.js") == 0) { duk_push_string(ctx, "#!ignored\nexports.foo = 123; exports.bar = 234;"); } else { duk_error(ctx, DUK_ERR_TYPE_ERROR, "cannot find module: %s", module_id); } return 1; }
/* * Called with a service object on the top of the stack. Returns with a message object on top of * the stack replacing the service object. */ static void MessageSetup(duk_context* ctx, const char* iface, const char* member, const char* path, uint8_t msgType) { AJ_Status status; AJ_MsgHeader hdr; AJ_Message msg; AJS_MsgInfo* msgInfo; const char* dest; uint8_t secure; size_t dlen; duk_idx_t objIdx = duk_push_object(ctx); /* * Get the destination from the service object */ duk_get_prop_string(ctx, -2, "dest"); dest = duk_get_lstring(ctx, -1, &dlen); duk_pop(ctx); /* * If this is not a broadcast message make sure the destination peer is still connected */ if (dlen) { CheckPeerIsAlive(ctx, dest); } /* * Initialize a message struct so we can lookup the message id. We do this now because it is * alot more efficient if the method object we are creating is used multiple times. */ memset(&msg, 0, sizeof(AJ_Message)); memset(&hdr, 0, sizeof(AJ_MsgHeader)); msg.hdr = &hdr; msg.signature = "*"; msg.member = member; msg.iface = iface; msg.objPath = path ? path : AJS_GetStringProp(ctx, -2, "path"); /* * This allows us to use one object table entry for all messages */ AJS_SetObjectPath(msg.objPath); hdr.msgType = msgType; status = AJ_LookupMessageId(&msg, &secure); if (status != AJ_OK) { duk_error(ctx, DUK_ERR_REFERENCE_ERROR, "Unknown %s %s", path ? "SIGNAL" : "METHOD", member); } /* * Buffer to caching message information stored in the "info" property on the method object */ msgInfo = duk_push_fixed_buffer(ctx, sizeof(AJS_MsgInfo) + dlen + 1); msgInfo->secure = secure; msgInfo->session = AJS_GetIntProp(ctx, -2, "session"); msgInfo->msgId = msg.msgId; memcpy(msgInfo->dest, dest, dlen); msgInfo->dest[dlen] = 0; duk_put_prop_string(ctx, objIdx, "info"); AJ_ASSERT(duk_get_top_index(ctx) == objIdx); /* * Remove sessions object and leave the message object on the top of the stack */ duk_remove(ctx, -2); }
static duk_ret_t test_error_return(duk_context *ctx, void *udata) { (void) udata; duk_set_top(ctx, 0); return duk_error(ctx, DUK_ERR_URI_ERROR, "invalid argument uri"); }
static int es_file_copy(duk_context *ctx) { char *cleanup; char path[URL_MAX]; char errbuf[256]; es_context_t *ec = es_get(ctx); const char *from = duk_to_string(ctx, 0); const char *to = duk_to_string(ctx, 1); cleanup = mystrdupa(to); fa_sanitize_filename(cleanup); snprintf(path, sizeof(path), "%s/copy/%s", ec->ec_storage, cleanup); TRACE(TRACE_DEBUG, "JS", "Copying file from '%s' to '%s'", from, path); if(fa_copy(path, from, errbuf, sizeof(errbuf))) duk_error(ctx, DUK_ERR_ERROR, "Copy failed: %s", errbuf); duk_push_string(ctx, path); return 1; }
/** * fd, buffer, offset, length, position */ static int es_file_write(duk_context *ctx) { es_fd_t *efd = es_fd_get(ctx, 0); duk_size_t bufsize; char *buf = duk_to_buffer(ctx, 1, &bufsize); int len; const int offset = duk_to_int(ctx, 2); if(duk_is_null(ctx, 3)) { len = bufsize; } else { len = duk_to_int(ctx, 3); } // Don't read past buffer end if(offset + len > bufsize) len = bufsize - offset; if(!duk_is_null(ctx, 4)) { // Seek fa_seek(efd->efd_fh, duk_require_number(ctx, 4), SEEK_SET); } int r = fa_write(efd->efd_fh, buf + offset, len); if(r < 0) duk_error(ctx, DUK_ERR_ERROR, "Write error to '%s'", efd->efd_path); duk_push_int(ctx, r); return 1; }
static duk_ret_t dukzip_zip_write(duk_context *ctx) { int res = ZIP_OK; zipFile archive = dukzip_zip_from_this(ctx); if (duk_is_string(ctx, 0)) { int outputl = 0; const char *output = duk_get_lstring(ctx, 0, &outputl); res = zipWriteInFileInZip(archive, output, outputl); } else if (duk_is_buffer(ctx, 0) || duk_is_object(ctx, 0)) { int outputl = 0; void *output = duk_require_buffer_data(ctx, 0, &outputl); res = zipWriteInFileInZip(archive, output, outputl); } else { duk_error(ctx, DUK_ERR_TYPE_ERROR, "unable to write argument to zip file (supported types: string, buffer)"); return -1; } if (res == ZIP_OK) { duk_push_true(ctx); } else { duk_push_false(ctx); } return 1; }
/* * Returns the IO functions supported by this pin */ static int NativeFunctionsGetter(duk_context* ctx) { uint8_t bit; uint8_t numFuncs = 0; const AJS_IO_Info* info; uint32_t pin; duk_push_this(ctx); pin = GetPinId(ctx, -1, 0); duk_pop(ctx); info = AJS_TargetIO_GetInfo(pin); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", pin); return 0; } duk_push_string(ctx, ", "); /* * Test each function bit */ for (bit = 0; bit < 32; ++bit) { if (info->functions & (1 << bit)) { const char* name = AJS_IO_FunctionName(1 << bit); duk_push_string(ctx, name); ++numFuncs; } } duk_join(ctx, numFuncs); return 1; }
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; }
static int NativeI2cTransfer(duk_context* ctx) { AJ_Status status; uint8_t addr = duk_require_int(ctx, 0); uint8_t* txBuf = NULL; uint8_t* rxBuf = NULL; duk_size_t txLen = 0; duk_size_t rxLen = 0; uint8_t rxBytes = 0; if (duk_is_undefined(ctx, 2)) { duk_push_undefined(ctx); } else { rxLen = duk_require_uint(ctx, 2); rxBuf = duk_push_dynamic_buffer(ctx, rxLen); } if (duk_is_null(ctx, 1)) { duk_push_undefined(ctx); } else { txBuf = SerializeToBuffer(ctx, 1, &txLen); } status = AJS_TargetIO_I2cTransfer(PinCtxPtr(ctx), addr, txBuf, txLen, rxBuf, rxLen, &rxBytes); if (status != AJ_OK) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "I2C transfer failed %s\n", AJ_StatusText(status)); } duk_pop(ctx); if (rxLen) { duk_resize_buffer(ctx, -1, rxBytes); } return 1; }
static duk_ret_t my_safe_func_error1(duk_context *ctx) { printf("hello from my_safe_func_error1\n"); duk_error(ctx, 123, "error thrown by my_safe_func_error1"); duk_push_int(ctx, 123); duk_push_int(ctx, 234); return 2; /* caller wants 1 ret only, so 123 is effective */ }
/* * Returns information about this pin */ static int NativeInfoGetter(duk_context* ctx) { int idx; uint32_t pin; const AJS_IO_Info* info; duk_push_this(ctx); pin = GetPinId(ctx, -1, 0); duk_pop(ctx); info = AJS_TargetIO_GetInfo(pin); if (!info) { duk_error(ctx, DUK_ERR_INTERNAL_ERROR, "Undefined I/O pin%d", pin); return 0; } duk_push_string(ctx, ", "); idx = duk_push_object(ctx); duk_push_int(ctx, info->physicalPin); duk_put_prop_string(ctx, idx, "physicalPin"); duk_push_string(ctx, info->schematicId); duk_put_prop_string(ctx, idx, "schematicId"); duk_push_string(ctx, info->datasheetId); duk_put_prop_string(ctx, idx, "datasheetId"); duk_push_string(ctx, info->description); duk_put_prop_string(ctx, idx, "description"); /* * Return the object we just created */ return 1; }
static duk_ret_t dukky_document_fragment_getElementById(duk_context *ctx) { /* ensure the parameters are present */ duk_idx_t dukky_argc = duk_get_top(ctx); if (dukky_argc < 1) { /* not enough arguments */ duk_error(ctx, DUK_RET_TYPE_ERROR, dukky_error_fmt_argument, 1, dukky_argc); } else if (dukky_argc > 1) { /* remove extraneous parameters */ duk_set_top(ctx, 1); } /* check types of passed arguments are correct */ if (dukky_argc > 0) { if (!duk_is_string(ctx, 0)) { duk_to_string(ctx, 0); } } /* Get private data for method */ document_fragment_private_t *priv = NULL; duk_push_this(ctx); duk_get_prop_string(ctx, -1, dukky_magic_string_private); priv = duk_get_pointer(ctx, -1); duk_pop_2(ctx); if (priv == NULL) { return 0; /* can do? No can do. */ } return 0; }