示例#1
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "on",
  "generate" : "jswrap_object_on",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"],
    ["listener","JsVar","The listener to call when this event is received"]
  ]
}
Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter.
 */
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvHasChildren(parent)) {
    jsWarn("Parent must be an object - not a String, Integer, etc.");
    return;
  }
  if (!jsvIsString(event)) {
    jsWarn("First argument to EventEmitter.on(..) must be a string");
    return;
  }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }

  JsVar *eventName = jsvVarPrintf(JS_EVENT_PREFIX"%s",event);
  if (!eventName) return; // no memory

  JsVar *eventList = jsvFindChildFromVar(parent, eventName, true);
  jsvUnLock(eventName);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewEmptyArray();
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock2(eventListeners, eventList);
  /* Special case if we're a data listener and data has already arrived then
   * we queue an event immediately. */
  if (jsvIsStringEqual(event, "data")) {
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (jsvIsString(buf)) {
      jsiQueueObjectCallbacks(parent, STREAM_CALLBACK_NAME, &buf, 1);
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    }
    jsvUnLock(buf);
  }
}
示例#2
0
/*JSON{
  "type" : "method",
  "class" : "Object",
  "name" : "on",
  "generate" : "jswrap_object_on",
  "params" : [
    ["event","JsVar","The name of the event, for instance 'data'"],
    ["listener","JsVar","The listener to call when this event is received"]
  ]
}
Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter.
*/
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvIsObject(parent)) {
      jsWarn("Parent must be a proper object - not a String, Integer, etc.");
      return;
    }
  if (!jsvIsString(event)) {
      jsWarn("First argument to EventEmitter.on(..) must be a string");
      return;
    }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }
  char eventName[16] = "#on";
  jsvGetString(event, &eventName[3], sizeof(eventName)-4);

  JsVar *eventList = jsvFindChildFromString(parent, eventName, true);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock(eventListeners);
  jsvUnLock(eventList);
  /* Special case if we're a data listener and data has already arrived then
   * we queue an event immediately. */
  if (jsvIsStringEqual(event, "data")) {
    JsVar *buf = jsvObjectGetChild(parent, STREAM_BUFFER_NAME, 0);
    if (jsvIsString(buf)) {
      jsiQueueObjectCallbacks(parent, "#ondata", &buf, 1);
      jsvRemoveNamedChild(parent, STREAM_BUFFER_NAME);
    }
    jsvUnLock(buf);
  }
}
示例#3
0
/*JSON{ "type":"function", "name" : "require",
         "description" : "Load the given module, and return the exported functions",
         "generate" : "jswrap_require",
         "params" : [ [ "moduleName", "JsVar", "A String containing the name of the given module"] ],
         "return" : ["JsVar", "The result of evaluating the string"]
}*/
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));
  if (jswIsBuiltInLibrary(moduleNameBuf)) {
    // create a 'fake' module that Espruino can use to map its built-in functions against
    moduleExport = jspNewBuiltin(moduleNameBuf);
  } else {
    // Now try and load it
    JsVar *fileContents = 0;
    //if (jsvIsStringEqual(moduleName,"http")) {}
    //if (jsvIsStringEqual(moduleName,"fs")) {}
  #ifdef USE_FILESYSTEM
    JsVar *modulePath = jsvNewFromString(
  #ifdef LINUX
        "node_modules/"
  #else
        "NODE_M~1/"
  #endif
        );
    if (!modulePath) { jsvUnLock(moduleExportName); return 0; } // out of memory
    jsvAppendStringVarComplete(modulePath, moduleName);
    jsvAppendString(modulePath,".js");
    fileContents = wrap_fat_readFile(modulePath);
    jsvUnLock(modulePath);
  #endif
    if (!fileContents || jsvIsStringEqual(fileContents,"")) {
      jsvUnLock(moduleExportName);
      jsvUnLock(fileContents);
      jsWarn("Module not found");
      return 0;
    }
    moduleExport = jspEvaluateModule(jsiGetParser(), fileContents);
    jsvUnLock(fileContents);
  }

  assert(moduleExport);
  jsvSetValueOfName(moduleExportName, moduleExport); // save in cache
  jsvUnLock(moduleExportName);
  return moduleExport;
}
示例#4
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Object",
  "name" : "setPrototypeOf",
  "generate" : "jswrap_object_setPrototypeOf",
  "params" : [
    ["object","JsVar","An object"],
    ["prototype","JsVar","The prototype to set on the object"]
  ],
  "return" : ["JsVar","The object passed in"]
}
Creates a new object with the specified prototype object and properties. properties are currently unsupported.
 */
JsVar *jswrap_object_setPrototypeOf(JsVar *object, JsVar *proto) {
  JsVar *v = jspGetNamedField(object, "__proto__", true);
  if (!jsvIsName(v)) {
    jsExceptionHere(JSET_TYPEERROR, "Can't extend this object\n");
  } else {
    jsvSetValueOfName(v, proto);
  }
  jsvUnLock(v);
  return jsvLockAgain(object);
}
示例#5
0
static JsVar* fsGetArray(const char *name, bool create) {
  JsVar *arrayName = jsvFindChildFromString(execInfo.root, name, create);
  JsVar *arr = jsvSkipName(arrayName);
  if (!arr && create) {
    arr = jsvNewWithFlags(JSV_ARRAY);
    jsvSetValueOfName(arrayName, arr);
  }
  jsvUnLock(arrayName);
  return arr;
}
示例#6
0
static void fileSetVar(JsFile *file) {
  JsVar *fHandle = jsvFindChildFromString(file->fileVar, JS_FS_DATA_NAME, true);
  JsVar *data = jsvSkipName(fHandle);
  if (!data) {
    data = jsvNewStringOfLength(sizeof(JsFileData));
    jsvSetValueOfName(fHandle, data);
  }
  jsvUnLock(fHandle);
  assert(data);
  jsvSetString(data, (char*)&file->data, sizeof(JsFileData));
  jsvUnLock(data);
}
示例#7
0
void graphicsSetVar(JsGraphics *gfx) {
  JsVar *dataname = jsvFindChildFromString(gfx->graphicsVar, JS_HIDDEN_CHAR_STR"gfx", true);
  JsVar *data = jsvSkipName(dataname);
  if (!data) {
    data = jsvNewStringOfLength(sizeof(JsGraphicsData));
    jsvSetValueOfName(dataname, data);
  }
  jsvUnLock(dataname);
  assert(data);
  jsvSetString(data, (char*)&gfx->data, sizeof(JsGraphicsData));
  jsvUnLock(data);
}
示例#8
0
static JsVar *jswrap_modules_getModuleList() {
  JsVar *moduleListName = jsvFindChildFromString(jsiGetParser()->root, JSPARSE_MODULE_CACHE_NAME, true);
  if (!moduleListName) return 0; // out of memory
  JsVar *moduleList = jsvSkipName(moduleListName);
  if (!moduleList) {
    moduleList = jsvNewWithFlags(JSV_OBJECT);
    if (!moduleList) { jsvUnLock(moduleListName); return 0; } // out of memory
    jsvSetValueOfName(moduleListName, moduleList); // no need to unlock
  }
  jsvUnLock(moduleListName);
  return moduleList;
}
/*JSON{ "type":"method", "class": "Object", "name" : "on",
         "description" : ["Register an event listener for this object, for instance ```http.on('data', function(d) {...})```. See Node.js's EventEmitter."],
         "generate" : "jswrap_object_on",
         "params" : [ [ "event", "JsVar", "The name of the event, for instance 'data'"],
                      [ "listener", "JsVar", "The listener to call when this event is received"] ]
}*/
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
  if (!jsvIsObject(parent)) {
      jsWarn("Parent must be a proper object - not a String, Integer, etc.");
      return;
    }
  if (!jsvIsString(event)) {
      jsWarn("First argument to EventEmitter.on(..) must be a string");
      return;
    }
  if (!jsvIsFunction(listener) && !jsvIsString(listener)) {
    jsWarn("Second argument to EventEmitter.on(..) must be a function or a String (containing code)");
    return;
  }
  char eventName[16] = "#on";
  jsvGetString(event, &eventName[3], sizeof(eventName)-4);

  JsVar *eventList = jsvFindChildFromString(parent, eventName, true);
  JsVar *eventListeners = jsvSkipName(eventList);
  if (jsvIsUndefined(eventListeners)) {
    // just add
    jsvSetValueOfName(eventList, listener);
  } else {
    if (jsvIsArray(eventListeners)) {
      // we already have an array, just add to it
      jsvArrayPush(eventListeners, listener);
    } else {
      // not an array - we need to make it an array
      JsVar *arr = jsvNewWithFlags(JSV_ARRAY);
      jsvArrayPush(arr, eventListeners);
      jsvArrayPush(arr, listener);
      jsvSetValueOfName(eventList, arr);
      jsvUnLock(arr);
    }
  }
  jsvUnLock(eventListeners);
  jsvUnLock(eventList);
}
示例#10
0
/*JSON{
  "type" : "staticmethod",
  "class" : "Object",
  "name" : "defineProperty",
  "generate" : "jswrap_object_defineProperty",
  "params" : [
    ["obj","JsVar","An object"],
    ["name","JsVar","The name of the property"],
    ["desc","JsVar","The property descriptor"]
  ],
  "return" : ["JsVar","The object, obj."]
}
Add a new property to the Object. 'Desc' is an object with the following fields:

* `configurable` (bool = false) - can this property be changed/deleted
* `enumerable` (bool = false) - can this property be enumerated
* `value` (anything) - the value of this property
* `writable` (bool = false) - can the value be changed with the assignment operator?
* `get` (function) - the getter function, or undefined if no getter
* `set` (function) - the setter function, or undefined if no setter
*
**Note:** `configurable`, `enumerable`, `writable`, `get`, and `set` are not implemented and will be ignored.
 */
JsVar *jswrap_object_defineProperty(JsVar *parent, JsVar *propName, JsVar *desc) {
  if (!jsvIsObject(parent)) {
    jsExceptionHere(JSET_ERROR, "First argument must be an object, got %t", parent);
    return 0;
  }
  if (!jsvIsObject(desc)) {
    jsExceptionHere(JSET_ERROR, "Property description must be an object, got %t", desc);
    return 0;
  }

  JsVar *name = jsvAsArrayIndex(propName);
  JsVar *value = jsvObjectGetChild(desc, "value", 0);
  JsVar *property = jsvFindChildFromVar(parent, name, true);
  jsvUnLock(name);
  if (property && value)
    jsvSetValueOfName(property, value);
  jsvUnLock2(property, value);

  return jsvLockAgain(parent);
}
示例#11
0
/*JSON{ "type":"staticmethod",
         "class" : "Modules", "name" : "addCached",
         "description" : "Add the given module to the cache",
         "generate" : "jswrap_modules_addCached",
         "params" : [ [ "id", "JsVar", "The module name to add" ],
                      [  "sourcecode", "JsVar", "The module's sourcecode" ] ]
}*/
void jswrap_modules_addCached(JsVar *id, JsVar *sourceCode) {
  if (!jsvIsString(id) || !jsvIsString(sourceCode)) {
    jsError("Both arguments to addCached must be strings");
    return;
  }

  JsVar *moduleList = jswrap_modules_getModuleList();
  if (!moduleList) return; // out of memory

  JsVar *moduleExport = jspEvaluateModule(jsiGetParser(), sourceCode);
  if (!moduleExport) {
    jsWarn("Unable to load module");
  } else {
    JsVar *moduleName = jsvFindChildFromVar(moduleList, id, true);
    if (moduleName) jsvSetValueOfName(moduleName, moduleExport);
    jsvUnLock(moduleExport);
  }
  jsvUnLock(moduleList);

}
示例#12
0
void _wlan_getIP_get_address(JsVar *object, const char *name,  unsigned char *ip, int nBytes, int base, char separator) {
  char data[64] = "";
  int i, l = 0;
  for (i=nBytes-1;i>=0;i--) {
    itoa(ip[i], &data[l], base);
    l = strlen(data);
    if (i>0 && separator) {
      data[l++] = separator;
      data[l] = 0;
    }
  }

  JsVar *dataVar = jsvNewFromString(data);
  if (!dataVar) return;

  JsVar *v = jsvFindChildFromString(object, name, true);
  if (!v) {
    jsvUnLock(dataVar);
    return; // out of memory
  }
  jsvSetValueOfName(v, dataVar);
  jsvUnLock(dataVar);
  jsvUnLock(v);
}
示例#13
0
static void NO_INLINE _eth_getIP_get_address(JsVar *object, const char *name,  unsigned char *ip, int nBytes, unsigned int base, char separator) {
  char data[64] = "";
  int i, l = 0;
  for (i=0;i<nBytes;i++) {
    itoa((int)ip[i], &data[l], base);
    l = (int)strlen(data);
    if (i<nBytes-1 && separator) {
      data[l++] = separator;
      data[l] = 0;
    }
  }

  JsVar *dataVar = jsvNewFromString(data);
  if (!dataVar) return;

  JsVar *v = jsvFindChildFromString(object, name, true);
  if (!v) {
    jsvUnLock(dataVar);
    return; // out of memory
  }
  jsvSetValueOfName(v, dataVar);
  jsvUnLock(dataVar);
  jsvUnLock(v);
}
示例#14
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;
}
示例#15
0
void jsvObjectIteratorSetValue(JsvObjectIterator *it, JsVar *value) {
  if (!it->var) return; // end of object
  jsvSetValueOfName(it->var, value);
}