示例#1
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Promise",
  "name" : "all",
  "generate" : "jswrap_promise_all",
  "params" : [
    ["promises","JsVar","An array of promises"]
  ],
  "return" : ["JsVar","A new Promise"]
}
Return a new promise that is resolved when all promises in the supplied
array are resolved.
*/
JsVar *jswrap_promise_all(JsVar *arr) {
  if (!jsvIsIterable(arr)) {
    jsExceptionHere(JSET_TYPEERROR, "Expecting something iterable, got %t", arr);
    return 0;
  }
  JsVar *promise = jspNewObject(0, "Promise");
  if (!promise) return 0;
  JsVar *resolve = jsvNewNativeFunction((void (*)(void))jswrap_promise_all_resolve, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS));
  JsVar *reject = jsvNewNativeFunction((void (*)(void))jswrap_promise_all_reject, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS));
  if (resolve && reject) {
    jsvObjectSetChild(resolve, JSPARSE_FUNCTION_THIS_NAME, promise);
    jsvObjectSetChild(reject, JSPARSE_FUNCTION_THIS_NAME, promise);
    int promises = 0;
    JsvObjectIterator it;
    jsvObjectIteratorNew(&it, arr);
    while (jsvObjectIteratorHasValue(&it)) {
      JsVar *p = jsvObjectIteratorGetValue(&it);
      jsvUnLock(jswrap_promise_then(p, resolve));
      jsvUnLock(jswrap_promise_catch(p, reject));
      jsvUnLock(p);
      promises++;
      jsvObjectIteratorNext(&it);
    }
    jsvObjectIteratorFree(&it);

    jsvObjectSetChildAndUnLock(promise, JS_PROMISE_COUNT_NAME, jsvNewFromInteger(promises));
    jsvObjectSetChildAndUnLock(promise, JS_PROMISE_RESULT_NAME, jsvNewEmptyArray());
  }
  jsvUnLock2(resolve, reject);
  return promise;
}
示例#2
0
/** A convenience function for adding event listeners */
void jswrap_object_addEventListener(JsVar *parent, const char *eventName, void (*callback)(), JsnArgumentType argTypes) {
  JsVar *n = jsvNewFromString(eventName);
  JsVar *cb = jsvNewNativeFunction(callback, argTypes);
  jswrap_object_on(parent, n, cb);
  jsvUnLock(cb);
  jsvUnLock(n);
}
示例#3
0
void _jswrap_promise_queuereject(JsVar *promise, JsVar *data) {
  JsVar *fn = jsvNewNativeFunction((void (*)(void))_jswrap_promise_reject, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS));
  if (!fn) return;
  jsvObjectSetChild(fn, JSPARSE_FUNCTION_THIS_NAME, promise);
  jsiQueueEvents(promise, fn, &data, 1);
  jsvUnLock(fn);
}
示例#4
0
/*JSON{
  "type" : "constructor",
  "class" : "Promise",
  "name" : "Promise",
  "generate" : "jswrap_promise_constructor",
  "params" : [
    ["executor","JsVar","A function of the form `function (resolve, reject)`"]
  ],
  "return" : ["JsVar","A Promise"]
}
Create a new Promise. The executor function is executed immediately (before the constructor even returns)
and
 */
JsVar *jswrap_promise_constructor(JsVar *executor) {
  JsVar *obj = jspNewObject(0, "Promise");
  if (obj) {
    // create resolve and reject
    JsVar *args[2] = {
        jsvNewNativeFunction((void (*)(void))_jswrap_promise_queueresolve, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS)),
        jsvNewNativeFunction((void (*)(void))_jswrap_promise_queuereject, JSWAT_VOID|JSWAT_THIS_ARG|(JSWAT_JSVAR<<JSWAT_BITS))
    };
    // bind 'this' to functions
    if (args[0]) jsvObjectSetChild(args[0], JSPARSE_FUNCTION_THIS_NAME, obj);
    if (args[1]) jsvObjectSetChild(args[1], JSPARSE_FUNCTION_THIS_NAME, obj);
    // call the executor
    jsvUnLock(jspeFunctionCall(executor, 0, obj, false, 2, args));
    jsvUnLockMany(2, args);
  }
  return obj;
}
示例#5
0
/*JSON{
  "type" : "function",
  "name" : "require",
  "generate" : "jswrap_require",
  "params" : [
    ["moduleName","JsVar","A String containing the name of the given module"]
  ],
  "return" : ["JsVar","The result of evaluating the string"]
}
Load the given module, and return the exported functions
 */
JsVar *jswrap_require(JsVar *moduleName) {
  if (!jsvIsString(moduleName)) {
    jsWarn("Expecting a module name as a string, but got %t", moduleName);
    return 0;
  }
  // Search to see if we have already loaded this module

  JsVar *moduleList = jswrap_modules_getModuleList();
  if (!moduleList) return 0; // out of memory
  JsVar *moduleExportName = jsvFindChildFromVar(moduleList, moduleName, true);
  jsvUnLock(moduleList);
  if (!moduleExportName) return 0; // out of memory
  JsVar *moduleExport = jsvSkipName(moduleExportName);
  if (moduleExport) {
    // Found the module!
    jsvUnLock(moduleExportName);
    return moduleExport;
  }

  // Now check if it is built-in
  char moduleNameBuf[32];
  jsvGetString(moduleName, moduleNameBuf, sizeof(moduleNameBuf));
  void *builtInLib = jswGetBuiltInLibrary(moduleNameBuf);
  if (builtInLib) {
    // create a 'fake' module that Espruino can use to map its built-in functions against
    moduleExport = jsvNewNativeFunction(builtInLib, 0);
  } else {
    // Now try and load it
    JsVar *fileContents = 0;
    //if (jsvIsStringEqual(moduleName,"http")) {}
    //if (jsvIsStringEqual(moduleName,"fs")) {}
#ifdef USE_FILESYSTEM
    JsVar *modulePath = jsvNewFromString("node_modules/");
    if (!modulePath) { jsvUnLock(moduleExportName); return 0; } // out of memory
    jsvAppendStringVarComplete(modulePath, moduleName);
    jsvAppendString(modulePath,".js");
    fileContents = jswrap_fs_readFile(modulePath);
    jsvUnLock(modulePath);
#endif
    if (!fileContents || jsvIsStringEqual(fileContents,"")) {
      jsvUnLock(moduleExportName);
      jsvUnLock(fileContents);
      jsWarn("Module %q not found", moduleName);
      return 0;
    }
    moduleExport = jspEvaluateModule(fileContents);
    jsvUnLock(fileContents);
  }

  if (moduleExport) // could have been out of memory
    jsvSetValueOfName(moduleExportName, moduleExport); // save in cache
  jsvUnLock(moduleExportName);
  return moduleExport;
}
示例#6
0
/*JSON{
  "type" : "staticmethod",
  "ifndef" : "SAVE_ON_FLASH",
  "class" : "E",
  "name" : "nativeCall",
  "generate" : "jswrap_espruino_nativeCall",
  "params" : [
    ["addr","int","The address in memory of the function"],
    ["sig","JsVar","The signature of the call, `returnType (arg1,arg2,...)`. Allowed types are `void`,`bool`,`int`,`double`,`Pin`,`JsVar`"]
  ],
  "return" : ["JsVar","The native function"]
}
ADVANCED: This is a great way to crash Espruino if you're not sure what you are doing

Create a native function that executes the code at the given address. Eg. `E.nativeCall(0x08012345,'double (double,double)')(1.1, 2.2)` 

If you're executing a thumb function, you'll almost certainly need to set the bottom bit of the address to 1.

Note it's not guaranteed that the call signature you provide can be used - it has to be something that a function in Espruino already uses.
*/
JsVar *jswrap_espruino_nativeCall(JsVarInt addr, JsVar *signature) {
  unsigned int argTypes = 0;
  if (jsvIsUndefined(signature)) {
    // Nothing to do
  } else if (jsvIsString(signature)) {
    JsLex lex;
    jslInit(&lex, signature);
    int argType;
    bool ok = true;
    int argNumber = 0;
    argType = nativeCallGetCType(&lex);
    if (argType>=0) argTypes |= (unsigned)argType << (JSWAT_BITS * argNumber++);
    else ok = false;
    if (ok) ok = jslMatch(&lex, '(');
    while (ok && lex.tk!=LEX_EOF && lex.tk!=')') {
      argType = nativeCallGetCType(&lex);
      if (argType>=0) {
        argTypes |= (unsigned)argType << (JSWAT_BITS * argNumber++);
        if (lex.tk!=')') ok = jslMatch(&lex, ',');
      } else ok = false;
    }
    if (ok) ok = jslMatch(&lex, ')');
    jslKill(&lex);
    if (argTypes & (unsigned int)~0xFFFF)
      ok = false;
    if (!ok) {
      jsExceptionHere(JSET_ERROR, "Error Parsing signature at argument number %d", argNumber);
      return 0;
    }
  } else {
    jsExceptionHere(JSET_ERROR, "Invalid Signature");
    return 0;
  }

  return jsvNewNativeFunction((void *)(size_t)addr, (unsigned short)argTypes);
}
示例#7
0
/*JSON{
  "type" : "method",
  "class" : "Function",
  "name" : "bind",
  "generate" : "jswrap_function_bind",
  "params" : [
    ["this","JsVar","The value to use as the 'this' argument when executing the function"],
    ["params","JsVarArray","Optional Default parameters that are prepended to the call"]
  ],
  "return" : ["JsVar","The 'bound' function"]
}
This executes the function with the supplied 'this' argument and parameters
 */
JsVar *jswrap_function_bind(JsVar *parent, JsVar *thisArg, JsVar *argsArray) {
  if (!jsvIsFunction(parent)) {
    jsExceptionHere(JSET_TYPEERROR, "Function.bind expects to be called on function, got %t", parent);
    return 0;
  }
  JsVar *fn;
  if (jsvIsNativeFunction(parent))
    fn = jsvNewNativeFunction(parent->varData.native.ptr, parent->varData.native.argTypes);
  else
    fn = jsvNewWithFlags(jsvIsFunctionReturn(parent) ? JSV_FUNCTION_RETURN : JSV_FUNCTION);
  if (!fn) return 0;

  // Old function info
  JsvObjectIterator fnIt;
  jsvObjectIteratorNew(&fnIt, parent);
  // add previously bound arguments
  while (jsvObjectIteratorHasValue(&fnIt)) {
    JsVar *param = jsvObjectIteratorGetKey(&fnIt);
    JsVar *defaultValue = jsvObjectIteratorGetValue(&fnIt);
    bool wasBound = jsvIsFunctionParameter(param) && defaultValue;
    if (wasBound) {
      JsVar *newParam = jsvCopy(param);
      if (newParam) { // could be out of memory
        jsvAddName(fn, newParam);
        jsvUnLock(newParam);
      }
    }
    jsvUnLock2(param, defaultValue);
    if (!wasBound) break;
    jsvObjectIteratorNext(&fnIt);
  }

  // add bound arguments
  JsvObjectIterator argIt;
  jsvObjectIteratorNew(&argIt, argsArray);
  while (jsvObjectIteratorHasValue(&argIt)) {
    JsVar *defaultValue = jsvObjectIteratorGetValue(&argIt);
    bool addedParam = false;
    while (!addedParam && jsvObjectIteratorHasValue(&fnIt)) {
      JsVar *param = jsvObjectIteratorGetKey(&fnIt);
      if (!jsvIsFunctionParameter(param)) {
        jsvUnLock(param);
        break;
      }
      JsVar *newParam = jsvCopyNameOnly(param, false,  true);
      jsvSetValueOfName(newParam, defaultValue);
      jsvAddName(fn, newParam);
      addedParam = true;
      jsvUnLock2(param, newParam);
      jsvObjectIteratorNext(&fnIt);
    }

    if (!addedParam) {
      JsVar *paramName = jsvNewFromEmptyString();
      if (paramName) {
        jsvMakeFunctionParameter(paramName); // force this to be called a function parameter
        jsvSetValueOfName(paramName, defaultValue);
        jsvAddName(fn, paramName);
        jsvUnLock(paramName);
      }
    }
    jsvUnLock(defaultValue);
    jsvObjectIteratorNext(&argIt);
  }
  jsvObjectIteratorFree(&argIt);

  // Copy the rest of the old function's info
  while (jsvObjectIteratorHasValue(&fnIt)) {
    JsVar *param = jsvObjectIteratorGetKey(&fnIt);
    JsVar *newParam = jsvCopyNameOnly(param, true, true);
    if (newParam) { // could be out of memory
      jsvAddName(fn, newParam);
      jsvUnLock(newParam);
    }
    jsvUnLock(param);
    jsvObjectIteratorNext(&fnIt);
  }
  jsvObjectIteratorFree(&fnIt);
  // Add 'this'
  jsvObjectSetChild(fn, JSPARSE_FUNCTION_THIS_NAME, thisArg); // no unlock needed

  return fn;
}
示例#8
0
void addNativeFunction(const char *name, void (*callbackPtr)(void)) {
  jsvUnLock(jsvObjectSetChild(execInfo.root, name, jsvNewNativeFunction(callbackPtr, JSWAT_VOID)));
}
示例#9
0
/*JSON{
  "type" : "init",
  "generate" : "jswrap_wice_init"
}*/
void jswrap_wice_init() {
  jspCallNamedFunction(execInfo.root, "USB.setConsole", 0, 0);
  jspEvaluate("USB.setConsole();");
#ifdef WICE_DEBUG
  WDEBUGLN("USB is console");
#endif
  /*JsVar *mode = jsvNewFromString("output");
  jswrap_io_pinMode(jshGetPinFromString(PIN_DASH7_XTAL_EN), mode);
  jswrap_io_pinMode(jshGetPinFromString(PIN_DASH7_RST), mode);
  jsvUnLock(mode);*/

  enableDASH();

  // Set up the DASH7 USART how we want it
  JshUSARTInfo inf;
  jshUSARTInitInfo(&inf);
  inf.baudRate = 115200;
  inf.pinRX = jshGetPinFromString(PIN_DASH7_RX);
  inf.pinTX = jshGetPinFromString(PIN_DASH7_TX);
  jshUSARTSetup(EV_SERIAL1, &inf);

  JsVar *serial = jspGetNamedField(execInfo.root, SERIAL1_DASH7, false);
  jswrap_object_addEventListener(serial, "data", dash7Callback, JSWAT_VOID | (JSWAT_JSVAR<<(JSWAT_BITS)));
  jsvUnLock(serial);

  startTime = jshGetSystemTime();

  wice_msg_init(&wifiMessage, wifiMessageBuffer, 2048);
  wice_msg_init(&dash7Message, dash7MessageBuffer, 256);


  options = jspEvaluate("x = {\"repeat\": \"true\", \"edge\": \"rising\", \"debounce\":\"50\"}");
  Pin btn = jshGetPinFromString("B10");
  JsVar *btnmode = jsvNewFromString("input");
  jswrap_io_pinMode(btn, btnmode);
  jsvUnLock(btnmode);

#ifdef GATEWAY
  WDEBUGLN("GATEWAY");
  blink(PIN_GRN, 50);
  /// opendrain and digitalwrite 1 will 'opencircuit it'
  /// http://www.espruino.com/Reference#l__global_pinMode
  JsVar *opendrain = jsvNewFromString("opendrain");
  WDEBUGSTRVAR(opendrain);
  jswrap_io_pinMode(jshGetPinFromString(PIN_ESP_GPIO_0), opendrain);
  jswrap_io_pinMode(jshGetPinFromString(PIN_ESP_GPIO_2), opendrain);
  jshPinOutput(jshGetPinFromString(PIN_ESP_GPIO_0), 1);
  jshPinOutput(jshGetPinFromString(PIN_ESP_GPIO_2), 1);
  jsvUnLock(opendrain);
  /// must opendrain gpio0/2 because of boot modes
  /// https://github.com/esp8266/esp8266-wiki/wiki/Boot-Process
  enableWifi();

  // Set up the Wifi USART how we want it
  JshUSARTInfo inf4;
  jshUSARTInitInfo(&inf4);
  inf4.baudRate = 115200;
  inf4.pinRX = jshGetPinFromString(PIN_ESP_RX);
  inf4.pinTX = jshGetPinFromString(PIN_ESP_TX);
  jshUSARTSetup(EV_SERIAL4, &inf4);

  /// make button restart wifi for gateway
  JsVar *restartWifi_fn = jsvNewNativeFunction(restartWifi, JSWAT_VOID);
  btnEvent = jswrap_interface_setWatch(restartWifi_fn,
                            btn, 
                            options);
  jsvUnLock(restartWifi_fn);
  /// configure wifi usart callback
  JsVar *wifiSerial = jspGetNamedField(execInfo.root, SERIAL4_WIFI, false);
  jswrap_object_addEventListener(wifiSerial, "data", wifiCallback, JSWAT_VOID | (JSWAT_JSVAR<<(JSWAT_BITS)));
  jsvUnLock(wifiSerial);
  doSendSerial();
#else 
  WDEBUGLN("NODE");
  blink(PIN_BLUE, 50);
  /// make button a forced measurement for nodes
  JsVar *doMeasurementAndWaitForResponse_fn = jsvNewNativeFunction(doMeasurementAndWaitForResponse, JSWAT_VOID);
  btnEvent = jswrap_interface_setWatch(doMeasurementAndWaitForResponse_fn,
                            btn, 
                            options);
  jsvUnLock(doMeasurementAndWaitForResponse_fn);

  /// set up main interval callback for nodes
  JsVar *doMeasurement_fn = jsvNewNativeFunction(doMeasurement, JSWAT_VOID);
  currentInterval = jswrap_interface_setInterval(doMeasurement_fn, INTERVAL, 0);
  jsvUnLock(doMeasurement_fn);

  /// prepare the I2C bus for talking with the Si7050 temp sensor
  JsVar *s = jspEvaluate("I2C1.setup({scl:B8, sda:B9, bitrate:50000});"); jsvUnLock(s);
  disableDASH();
  jswrap_interface_setDeepSleep(true); //do deep sleep [TODO can we wake on press?]
#endif
}