JSObject* Library::Create(JSContext* cx, HandleValue path, const JSCTypesCallbacks* callbacks) { RootedObject libraryObj(cx, JS_NewObject(cx, &sLibraryClass)); if (!libraryObj) return nullptr; // initialize the library JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PrivateValue(nullptr)); // attach API functions if (!JS_DefineFunctions(cx, libraryObj, sLibraryFunctions)) return nullptr; if (!path.isString()) { JS_ReportErrorASCII(cx, "open takes a string argument"); return nullptr; } PRLibSpec libSpec; RootedFlatString pathStr(cx, JS_FlattenString(cx, path.toString())); if (!pathStr) return nullptr; AutoStableStringChars pathStrChars(cx); if (!pathStrChars.initTwoByte(cx, pathStr)) return nullptr; #ifdef XP_WIN // On Windows, converting to native charset may corrupt path string. // So, we have to use Unicode path directly. char16ptr_t pathChars = pathStrChars.twoByteChars(); libSpec.value.pathname_u = pathChars; libSpec.type = PR_LibSpec_PathnameU; #else // Convert to platform native charset if the appropriate callback has been // provided. char* pathBytes; if (callbacks && callbacks->unicodeToNative) { pathBytes = callbacks->unicodeToNative(cx, pathStrChars.twoByteChars(), pathStr->length()); if (!pathBytes) return nullptr; } else { // Fallback: assume the platform native charset is UTF-8. This is true // for Mac OS X, Android, and probably Linux. size_t nbytes = GetDeflatedUTF8StringLength(cx, pathStrChars.twoByteChars(), pathStr->length()); if (nbytes == (size_t) -1) return nullptr; pathBytes = static_cast<char*>(JS_malloc(cx, nbytes + 1)); if (!pathBytes) return nullptr; ASSERT_OK(DeflateStringToUTF8Buffer(cx, pathStrChars.twoByteChars(), pathStr->length(), pathBytes, &nbytes)); pathBytes[nbytes] = 0; } libSpec.value.pathname = pathBytes; libSpec.type = PR_LibSpec_Pathname; #endif PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW); #ifndef XP_WIN JS_free(cx, pathBytes); #endif if (!library) { #define MAX_ERROR_LEN 1024 char error[MAX_ERROR_LEN] = "Cannot get error from NSPR."; uint32_t errorLen = PR_GetErrorTextLength(); if (errorLen && errorLen < MAX_ERROR_LEN) PR_GetErrorText(error); #undef MAX_ERROR_LEN if (JS::StringIsASCII(error)) { JSAutoByteString pathCharsUTF8; if (pathCharsUTF8.encodeUtf8(cx, pathStr)) JS_ReportErrorUTF8(cx, "couldn't open library %s: %s", pathCharsUTF8.ptr(), error); } else { JSAutoByteString pathCharsLatin1; if (pathCharsLatin1.encodeLatin1(cx, pathStr)) JS_ReportErrorLatin1(cx, "couldn't open library %s: %s", pathCharsLatin1.ptr(), error); } return nullptr; } // stash the library JS_SetReservedSlot(libraryObj, SLOT_LIBRARY, PrivateValue(library)); return libraryObj; }
JSObject* Library::Create(JSContext* cx, jsval path, JSCTypesCallbacks* callbacks) { JSObject* libraryObj = JS_NewObject(cx, &sLibraryClass, NULL, NULL); if (!libraryObj) return NULL; js::AutoObjectRooter root(cx, libraryObj); // initialize the library if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(NULL))) return NULL; // attach API functions if (!JS_DefineFunctions(cx, libraryObj, sLibraryFunctions)) return NULL; if (!JSVAL_IS_STRING(path)) { JS_ReportError(cx, "open takes a string argument"); return NULL; } PRLibSpec libSpec; JSFlatString* pathStr = JS_FlattenString(cx, JSVAL_TO_STRING(path)); if (!pathStr) return NULL; #ifdef XP_WIN // On Windows, converting to native charset may corrupt path string. // So, we have to use Unicode path directly. const PRUnichar* pathChars = JS_GetFlatStringChars(pathStr); if (!pathChars) return NULL; libSpec.value.pathname_u = pathChars; libSpec.type = PR_LibSpec_PathnameU; #else // Convert to platform native charset if the appropriate callback has been // provided. char* pathBytes; if (callbacks && callbacks->unicodeToNative) { pathBytes = callbacks->unicodeToNative(cx, pathStr->chars(), pathStr->length()); if (!pathBytes) return NULL; } else { // Fallback: assume the platform native charset is UTF-8. This is true // for Mac OS X, Android, and probably Linux. size_t nbytes = GetDeflatedUTF8StringLength(cx, pathStr->chars(), pathStr->length()); if (nbytes == (size_t) -1) return NULL; pathBytes = static_cast<char*>(JS_malloc(cx, nbytes + 1)); if (!pathBytes) return NULL; ASSERT_OK(DeflateStringToUTF8Buffer(cx, pathStr->chars(), pathStr->length(), pathBytes, &nbytes)); pathBytes[nbytes] = 0; } libSpec.value.pathname = pathBytes; libSpec.type = PR_LibSpec_Pathname; #endif PRLibrary* library = PR_LoadLibraryWithFlags(libSpec, 0); #ifndef XP_WIN JS_free(cx, pathBytes); #endif if (!library) { JS_ReportError(cx, "couldn't open library"); return NULL; } // stash the library if (!JS_SetReservedSlot(cx, libraryObj, SLOT_LIBRARY, PRIVATE_TO_JSVAL(library))) return NULL; return libraryObj; }