From 6af256bc53e5c7eba63e3df64638ad5f1da99711 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Thu, 22 Sep 2011 21:08:40 -0400 Subject: [PATCH] Add first crude binary module implementation. --- .hgignore | 7 + binary/chrome.manifest | 5 + binary/config.mk | 24 ++ binary/install.rdf | 20 ++ binary/src/Makefile | 79 ++++++ binary/src/dactylIUtils.idl | 30 ++ binary/src/dactylModule.cpp | 40 +++ binary/src/dactylUtils.cpp | 297 ++++++++++++++++++++ binary/src/dactylUtils.h | 34 +++ binary/src/mozJSLoaderUtils.cpp | 199 +++++++++++++ binary/src/mozJSLoaderUtils.h | 66 +++++ binary/src/subscriptLoader.cpp | 479 ++++++++++++++++++++++++++++++++ common/modules/commands.jsm | 9 +- common/modules/io.jsm | 2 +- common/modules/overlay.jsm | 2 +- common/modules/services.jsm | 1 + common/modules/util.jsm | 2 +- 17 files changed, 1290 insertions(+), 6 deletions(-) create mode 100644 binary/chrome.manifest create mode 100644 binary/config.mk create mode 100644 binary/install.rdf create mode 100644 binary/src/Makefile create mode 100644 binary/src/dactylIUtils.idl create mode 100644 binary/src/dactylModule.cpp create mode 100644 binary/src/dactylUtils.cpp create mode 100644 binary/src/dactylUtils.h create mode 100644 binary/src/mozJSLoaderUtils.cpp create mode 100644 binary/src/mozJSLoaderUtils.h create mode 100644 binary/src/subscriptLoader.cpp diff --git a/.hgignore b/.hgignore index d64ebbc0..fcc3ad80 100644 --- a/.hgignore +++ b/.hgignore @@ -8,6 +8,11 @@ syntax: glob ## Generated by the build process *.xpi +*.o +*.so +*.xpt +*/.depend +*/config.local.mk */locale/*/*.html */chrome */contrib/vim/*.vba @@ -15,6 +20,8 @@ syntax: glob downloads/* .git/* +binary/src/*/*.h + common/tests/functional/log *.py[co] diff --git a/binary/chrome.manifest b/binary/chrome.manifest new file mode 100644 index 00000000..2af7f6ad --- /dev/null +++ b/binary/chrome.manifest @@ -0,0 +1,5 @@ + +interfaces components/dactylIUtils.xpt +binary-component components/9.0-Linux_x86_64-gcc3/dactyl.so abi=Linux_x86_64-gcc3 platformversion>=9.0 platformversion<9.* + +# vim:se tw=0 ft=cfg: diff --git a/binary/config.mk b/binary/config.mk new file mode 100644 index 00000000..5311c24a --- /dev/null +++ b/binary/config.mk @@ -0,0 +1,24 @@ + +PLATFORM = 9.0-Linux_x86_64-gcc3 +DEFINES = -DGECKO_MAJOR=9 -DGECKO_MINOR=0 + +SED ?= sed -r + +GECKO_SDK_PATH := $(shell pkg-config --libs libxul | $(SED) 's,([^-]|-[^L])*-L([^ ]+)/lib.*,\2,') + +CXX ?= c++ + +MKDEP ?= $(CXX) -M + +PYTHON ?= python2 + +CPPFLAGS += -fno-rtti \ + -fno-exceptions \ + -fshort-wchar \ + -fPIC \ + $(NULL) + +XPIDL ?= $(PYTHON) $(GECKO_SDK_PATH)/sdk/bin +IDL_H ?= $(XPIDL)/header.py -o +IDL_XPT ?= $(XPIDL)/typelib.py -o + diff --git a/binary/install.rdf b/binary/install.rdf new file mode 100644 index 00000000..4fc8e5ad --- /dev/null +++ b/binary/install.rdf @@ -0,0 +1,20 @@ + + + + + + + + + + + diff --git a/binary/src/Makefile b/binary/src/Makefile new file mode 100644 index 00000000..774135c2 --- /dev/null +++ b/binary/src/Makefile @@ -0,0 +1,79 @@ +ROOT = .. + +XPTDIR = $(ROOT)/components/ +SODIR = $(ROOT)/components/$(PLATFORM)/ +OBJDIR = $(PLATFORM)/ + +MODULE = $(SODIR)dactyl + +XPIDLSRCS = \ + dactylIUtils.idl \ + $(NULL) + +CPPSRCS = \ + dactylModule.cpp \ + dactylUtils.cpp \ + mozJSLoaderUtils.cpp \ + subscriptLoader.cpp \ + $(NULL) + +GECKO_CONFIG_INCLUDE = -include mozilla-config.h + +GECKO_DEFINES = -DMOZILLA_STRICT_API + +GECKO_INCLUDES = -I$(PLATFORM)/ \ + -I$(GECKO_SDK_PATH) \ + -I$(GECKO_SDK_PATH)/idl \ + -I$(GECKO_SDK_PATH)/include + +GECKO_LDFLAGS = -L$(GECKO_SDK_PATH)/bin \ + -L$(GECKO_SDK_PATH)/lib \ + -lxpcomglue_s \ + -lnspr4 \ + -lplds4 \ + -lxul \ + -shared \ + $(NULL) + +include $(ROOT)/config.mk +sinclude $(ROOT)/config.local.mk + +XPTS = $(XPIDLSRCS:%.idl=$(XPTDIR)%.xpt) +OBJS = $(CPPSRCS:%.cpp=$(OBJDIR)%.o) +HEADERS = $(XPIDLSRCS:%.idl=$(PLATFORM)/%.h) + +all: build + +$(OBJS): $(HEADERS) + +$(PLATFORM)/%.h: %.idl + $(IDL_H) $@ $(GECKO_INCLUDES) $< + +$(XPTDIR)%.xpt: %.idl + $(IDL_XPT) $@ $(GECKO_INCLUDES) $< + +depend: .depend + +_CPPFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(GECKO_CONFIG_INCLUDE) $(GECKO_DEFINES) $(GECKO_INCLUDES) $(DEFINES) + +$(OBJDIR)%.o: %.cpp Makefile + $(CXX) -o $@ -c $(_CPPFLAGS) $< + +.depend: $(CPPSRCS) Makefile + $(MKDEP) $(_CPPFLAGS) $(CPPSRCS) | $(SED) 's;^[^ ];$(OBJDIR)&;' >.depend + +$(MODULE).so: $(OBJS) + $(CXX) -o $@ -Wl,-soname=$(MODULE).so $(OBJS) $(GECKO_LDFLAGS) + chmod +x $@ + +dirs: $(XPTDIR) $(SODIR) $(OBJDIR) + +$(XPTDIR) $(SODIR) $(OBJDIR): + mkdir -p $@ + +build: dirs $(XPTS) $(MODULE).so + +clean: + rm $(MODULE).so + +sinclude .depend diff --git a/binary/src/dactylIUtils.idl b/binary/src/dactylIUtils.idl new file mode 100644 index 00000000..84f941af --- /dev/null +++ b/binary/src/dactylIUtils.idl @@ -0,0 +1,30 @@ +/* Public Domain */ + +#include "nsISupports.idl" + +%{C++ +#include "jsapi.h" +%} + + +[scriptable, uuid(29d1c61f-5959-42b3-8a13-4b473b2b47bf)] +interface dactylIUtils : nsISupports +{ + [implicit_jscontext] + jsval createGlobal(); + + [implicit_jscontext] + jsval evalInContext(in AString source, + in jsval target, + [optional] in ACString filename, + [optional] in PRInt32 lineNumber); + + [implicit_jscontext] + jsval getGlobalForObject(in jsval object); + + void loadSubScript (in wstring url + /* [optional] in jsval context, */ + /* [optional] in wstring charset */); +}; + +/* vim:se sts=4 sw=4 et ft=idl: */ diff --git a/binary/src/dactylModule.cpp b/binary/src/dactylModule.cpp new file mode 100644 index 00000000..21625d8c --- /dev/null +++ b/binary/src/dactylModule.cpp @@ -0,0 +1,40 @@ +#include "dactylUtils.h" + +#include "mozilla/ModuleUtils.h" + +#define NS_DACTYLUTILS_CID \ +{ 0x4d55a47c, 0x0627, 0x4339, \ + { 0x97, 0x91, 0x52, 0xef, 0x5e, 0xd4, 0xc3, 0xd1 } } + +#define NS_DACTYLUTILS_CONTRACTID \ + "@dactyl.googlecode.com/extra/utils" + +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(dactylUtils, Init) + +NS_DEFINE_NAMED_CID(NS_DACTYLUTILS_CID); + +static const mozilla::Module::CIDEntry kDactylCIDs[] = { + { &kNS_DACTYLUTILS_CID, true, NULL, dactylUtilsConstructor }, + { NULL } +}; + +static const mozilla::Module::ContractIDEntry kDactylContracts[] = { + { NS_DACTYLUTILS_CONTRACTID, &kNS_DACTYLUTILS_CID }, + { NULL } +}; + +static const mozilla::Module::CategoryEntry kDactylCategories[] = { + { NULL } +}; + +static const mozilla::Module kDactylUtilsModule = { + mozilla::Module::kVersion, + kDactylCIDs, + kDactylContracts, + kDactylCategories, + NULL, + NULL, + NULL +}; + +NSMODULE_DEFN(dactylUtilsModule) = &kDactylUtilsModule; diff --git a/binary/src/dactylUtils.cpp b/binary/src/dactylUtils.cpp new file mode 100644 index 00000000..03c8f67a --- /dev/null +++ b/binary/src/dactylUtils.cpp @@ -0,0 +1,297 @@ +/* + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Contributors, possibly: + * Kris Maglione + * Jeff Walden + * Mike Shaver + * John Bandhauer + * Robert Ginda + * Pierre Phaneuf + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** + */ + +#include "dactylUtils.h" + +#include "jsdbgapi.h" +#include "jsobj.h" + +#include "nsIObserverService.h" +#include "nsIScriptSecurityManager.h" +#include "nsIXPCScriptable.h" + +#include "nsComponentManagerUtils.h" +#include "nsServiceManagerUtils.h" +#include "nsStringAPI.h" + + +class autoDropPrincipals { +public: + autoDropPrincipals(JSContext *context, JSPrincipals *principals) : mContext(context), mJSPrincipals(principals) {} + ~autoDropPrincipals() { + JSPRINCIPALS_DROP(mContext, mJSPrincipals); + } + +private: + JSContext *mContext; + JSPrincipals *mJSPrincipals; +}; + +static JSBool +Dump(JSContext *cx, uintN argc, jsval *vp) +{ + JSString *str; + if (!argc) + return JS_TRUE; + + str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]); + if (!str) + return JS_FALSE; + + size_t length; + const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length); + if (!chars) + return JS_FALSE; + + fputs(NS_ConvertUTF16toUTF8(reinterpret_cast(chars)).get(), stderr); + return JS_TRUE; +} + +static JSFunctionSpec gGlobalFun[] = { + {"dump", Dump, 1,0}, + {nsnull,nsnull,0,0} +}; + +static dactylUtils* gService = nsnull; + +dactylUtils::dactylUtils() + : mRuntime(nsnull) +{ + NS_ASSERTION(gService == nsnull, "Service already exists"); +} + +dactylUtils::~dactylUtils() +{ + mRuntimeService = nsnull; + gService = nsnull; +} + +nsresult +dactylUtils::Init() +{ + nsresult rv; + NS_ENSURE_TRUE(!gService, NS_ERROR_UNEXPECTED); + + mRuntimeService = do_GetService("@mozilla.org/js/xpc/RuntimeService;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mRuntimeService->GetRuntime(&mRuntime); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr secman = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + NS_ENSURE_TRUE(secman, NS_ERROR_FAILURE); + + rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal)); + NS_ENSURE_TRUE(rv, rv); + NS_ENSURE_TRUE(mSystemPrincipal, NS_ERROR_FAILURE); + + return NS_OK; +} + +NS_IMPL_ISUPPORTS1(dactylUtils, + dactylIUtils) + +NS_IMETHODIMP +dactylUtils::CreateGlobal(JSContext *cx, jsval *out) +{ + nsresult rv; + + // JS::AutoPreserveCompartment pc(cx); + + nsCOMPtr backstagePass; + rv = mRuntimeService->GetBackstagePass(getter_AddRefs(backstagePass)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr xpc = + do_GetService("@mozilla.org/js/xpc/XPConnect;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // Make sure InitClassesWithNewWrappedGlobal() installs the + // backstage pass as the global in our compilation context. + JS_SetGlobalObject(cx, nsnull); + + nsCOMPtr holder; + rv = xpc->InitClassesWithNewWrappedGlobal(cx, backstagePass, + NS_GET_IID(nsISupports), + mSystemPrincipal, + nsnull, + nsIXPConnect:: + FLAG_SYSTEM_GLOBAL_OBJECT, + getter_AddRefs(holder)); + NS_ENSURE_SUCCESS(rv, rv); + + JSObject *global; + rv = holder->GetJSObject(&global); + NS_ENSURE_SUCCESS(rv, rv); + + JSAutoEnterCompartment ac; + NS_ENSURE_TRUE(ac.enter(cx, global), NS_ERROR_FAILURE); + + NS_ENSURE_TRUE(JS_DefineFunctions(cx, global, gGlobalFun), + NS_ERROR_FAILURE); + NS_ENSURE_TRUE(JS_DefineProfilingFunctions(cx, global), + NS_ERROR_FAILURE); + + *out = OBJECT_TO_JSVAL(global); +} + +NS_IMETHODIMP +dactylUtils::EvalInContext(const nsAString &aSource, + const jsval &aTarget, + const nsACString &aFilename, + PRInt32 aLineNumber, + JSContext *cx, + jsval *rval) +{ + nsresult rv; + + nsCOMPtr xpc(do_GetService(nsIXPConnect::GetCID(), &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString filename; + + if (!aFilename.IsEmpty()) + filename.Assign(aFilename); + else { + nsCOMPtr frame; + xpc->GetCurrentJSStack(getter_AddRefs(frame)); + NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE); + frame->GetFilename(getter_Copies(filename)); + frame->GetLineNumber(&aLineNumber); + } + + JSObject *target; + NS_ENSURE_FALSE(JSVAL_IS_PRIMITIVE(aTarget), NS_ERROR_UNEXPECTED); + target = JSVAL_TO_OBJECT(aTarget); + + + JSObject *result = target; + target = JS_FindCompilationScope(cx, target); + NS_ENSURE_TRUE(target, NS_ERROR_FAILURE); + + + nsCOMPtr secman = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + NS_ENSURE_TRUE(secman, NS_ERROR_FAILURE); + + nsCOMPtr principal; + rv = secman->GetObjectPrincipal(cx, target, getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + + + JSPrincipals *jsPrincipals; + rv = principal->GetJSPrincipals(cx, &jsPrincipals); + NS_ENSURE_SUCCESS(rv, rv); + autoDropPrincipals adp(cx, jsPrincipals); + + JSObject *callingScope; + { + JSAutoRequest req(cx); + + callingScope = JS_GetScopeChain(cx); + NS_ENSURE_TRUE(callingScope, NS_ERROR_FAILURE); + callingScope = JS_GetGlobalForObject(cx, callingScope); + } + + { + JSAutoRequest req(cx); + JSAutoEnterCompartment ac; + jsval v; + + NS_ENSURE_TRUE(ac.enter(cx, target), NS_ERROR_FAILURE); + + JSBool ok = + JS_EvaluateUCScriptForPrincipals(cx, target, + jsPrincipals, + reinterpret_cast + (PromiseFlatString(aSource).get()), + aSource.Length(), + filename.get(), aLineNumber, &v); + + if (!ok) { + jsval exn; + if (!JS_GetPendingException(cx, &exn)) + rv = NS_ERROR_FAILURE; + else { + JS_ClearPendingException(cx); + + if (JS_WrapValue(cx, &exn)) + JS_SetPendingException(cx, exn); + } + } + else { + // Convert the result into something safe for our caller. + JSAutoRequest req(cx); + JSAutoEnterCompartment ac; + + if (!ac.enter(cx, callingScope) || !JS_WrapValue(cx, &v)) + rv = NS_ERROR_FAILURE; + + if (NS_SUCCEEDED(rv)) + *rval = v; + } + } + + return rv; +} + +NS_IMETHODIMP +dactylUtils::GetGlobalForObject(const jsval &aObject, + JSContext *cx, + jsval *rval) +{ + nsresult rv; + + NS_ENSURE_FALSE(JSVAL_IS_PRIMITIVE(aObject), + NS_ERROR_XPC_BAD_CONVERT_JS); + + JSObject *obj = JSVAL_TO_OBJECT(aObject); + if (obj->isProxy()) + obj = obj->unwrap(); + + JSObject *global = JS_GetGlobalForObject(cx, obj); + *rval = OBJECT_TO_JSVAL(global); + + // Outerize if necessary. + if (JSObjectOp outerize = global->getClass()->ext.outerObject) + *rval = OBJECT_TO_JSVAL(outerize(cx, global)); + + return NS_OK; +} + +/* vim:se sts=4 sw=4 et ft=cpp: */ diff --git a/binary/src/dactylUtils.h b/binary/src/dactylUtils.h new file mode 100644 index 00000000..fd918497 --- /dev/null +++ b/binary/src/dactylUtils.h @@ -0,0 +1,34 @@ + +#pragma once + +#include "dactylIUtils.h" + +#include "nsISupports.h" +#include "nsIPrincipal.h" +#include "nsIXPConnect.h" + +#include "jsapi.h" +#include "jsfriendapi.h" +#include "nsIJSRuntimeService.h" +#include "nsIJSContextStack.h" + +#include "nsCOMPtr.h" + +class dactylUtils : public dactylIUtils { +public: + dactylUtils() NS_HIDDEN; + ~dactylUtils() NS_HIDDEN; + + NS_DECL_ISUPPORTS + NS_DECL_DACTYLIUTILS + + NS_HIDDEN_(nsresult) Init(); + +private: + + nsCOMPtr mRuntimeService; + JSRuntime *mRuntime; + + nsCOMPtr mSystemPrincipal; +}; + diff --git a/binary/src/mozJSLoaderUtils.cpp b/binary/src/mozJSLoaderUtils.cpp new file mode 100644 index 00000000..c9cfb91c --- /dev/null +++ b/binary/src/mozJSLoaderUtils.cpp @@ -0,0 +1,199 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2010-2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#define JS_XDRScript JS_XDRScriptObject + +#include "mozJSLoaderUtils.h" +#include "nsAutoPtr.h" +#include "nsScriptLoader.h" + +#include "jsapi.h" +#include "jsxdrapi.h" + +#include "mozilla/scache/StartupCache.h" +#include "mozilla/scache/StartupCacheUtils.h" + +#include "nsIChromeRegistry.h" +#include "nsIIOService.h" +#include "nsIResProtocolHandler.h" +#include "nsNetUtil.h" + +using namespace mozilla::scache; + +static nsresult +ReadScriptFromStream(JSContext *cx, nsIObjectInputStream *stream, + JSScript **script) +{ + *script = nsnull; + + PRUint32 size; + nsresult rv = stream->Read32(&size); + NS_ENSURE_SUCCESS(rv, rv); + + char *data; + rv = stream->ReadBytes(size, &data); + NS_ENSURE_SUCCESS(rv, rv); + + JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_DECODE); + NS_ENSURE_TRUE(xdr, NS_ERROR_OUT_OF_MEMORY); + + xdr->userdata = stream; + JS_XDRMemSetData(xdr, data, size); + + if (!JS_XDRScript(xdr, script)) { + rv = NS_ERROR_FAILURE; + } + + // Update data in case ::JS_XDRScript called back into C++ code to + // read an XPCOM object. + // + // In that case, the serialization process must have flushed a run + // of counted bytes containing JS data at the point where the XPCOM + // object starts, after which an encoding C++ callback from the JS + // XDR code must have written the XPCOM object directly into the + // nsIObjectOutputStream. + // + // The deserialization process will XDR-decode counted bytes up to + // but not including the XPCOM object, then call back into C++ to + // read the object, then read more counted bytes and hand them off + // to the JSXDRState, so more JS data can be decoded. + // + // This interleaving of JS XDR data and XPCOM object data may occur + // several times beneath the call to ::JS_XDRScript, above. At the + // end of the day, we need to free (via nsMemory) the data owned by + // the JSXDRState. So we steal it back, nulling xdr's buffer so it + // doesn't get passed to ::JS_free by ::JS_XDRDestroy. + + uint32 length; + data = static_cast(JS_XDRMemGetData(xdr, &length)); + JS_XDRMemSetData(xdr, nsnull, 0); + JS_XDRDestroy(xdr); + + // If data is null now, it must have been freed while deserializing an + // XPCOM object (e.g., a principal) beneath ::JS_XDRScript. + nsMemory::Free(data); + + return rv; +} + +static nsresult +WriteScriptToStream(JSContext *cx, JSScript *script, + nsIObjectOutputStream *stream) +{ + JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_ENCODE); + NS_ENSURE_TRUE(xdr, NS_ERROR_OUT_OF_MEMORY); + + xdr->userdata = stream; + nsresult rv = NS_OK; + + if (JS_XDRScript(xdr, &script)) { + // Get the encoded JSXDRState data and write it. The JSXDRState owns + // this buffer memory and will free it beneath ::JS_XDRDestroy. + // + // If an XPCOM object needs to be written in the midst of the JS XDR + // encoding process, the C++ code called back from the JS engine (e.g., + // nsEncodeJSPrincipals in caps/src/nsJSPrincipals.cpp) will flush data + // from the JSXDRState to aStream, then write the object, then return + // to JS XDR code with xdr reset so new JS data is encoded at the front + // of the xdr's data buffer. + // + // However many XPCOM objects are interleaved with JS XDR data in the + // stream, when control returns here from ::JS_XDRScript, we'll have + // one last buffer of data to write to aStream. + + uint32 size; + const char* data = reinterpret_cast + (JS_XDRMemGetData(xdr, &size)); + NS_ASSERTION(data, "no decoded JSXDRState data!"); + + rv = stream->Write32(size); + if (NS_SUCCEEDED(rv)) { + rv = stream->WriteBytes(data, size); + } + } else { + rv = NS_ERROR_FAILURE; // likely to be a principals serialization error + } + + JS_XDRDestroy(xdr); + return rv; +} + +nsresult +ReadCachedScript(nsIStartupCache* cache, nsACString &uri, JSContext *cx, JSScript **script) +{ + nsresult rv; + + nsAutoArrayPtr buf; + PRUint32 len; + rv = cache->GetBuffer(PromiseFlatCString(uri).get(), getter_Transfers(buf), + &len); + if (NS_FAILED(rv)) { + return rv; // don't warn since NOT_AVAILABLE is an ok error + } + + nsCOMPtr ois; + rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(ois)); + NS_ENSURE_SUCCESS(rv, rv); + buf.forget(); + + return ReadScriptFromStream(cx, ois, script); +} + +nsresult +WriteCachedScript(nsIStartupCache* cache, nsACString &uri, JSContext *cx, JSScript *script) +{ + nsresult rv; + + nsCOMPtr oos; + nsCOMPtr storageStream; + rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(oos), + getter_AddRefs(storageStream), + true); + NS_ENSURE_SUCCESS(rv, rv); + + rv = WriteScriptToStream(cx, script, oos); + oos->Close(); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoArrayPtr buf; + PRUint32 len; + rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), &len); + NS_ENSURE_SUCCESS(rv, rv); + + rv = cache->PutBuffer(PromiseFlatCString(uri).get(), buf, len); + return rv; +} diff --git a/binary/src/mozJSLoaderUtils.h b/binary/src/mozJSLoaderUtils.h new file mode 100644 index 00000000..0b47b947 --- /dev/null +++ b/binary/src/mozJSLoaderUtils.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org. + * + * The Initial Developer of the Original Code is + * Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Wu + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef mozJSLoaderUtils_h +#define mozJSLoaderUtils_h + +#include "nsIStartupCache.h" +#include "nsStringAPI.h" +#include "jsapi.h" + +class nsIURI; + +namespace mozilla { +namespace scache { +class StartupCache; +} +} + +#include "nsIWeakReferenceUtils.h" +typedef nsString nsAFlatString; +#include "nsScriptLoader.h" + +nsresult +ReadCachedScript(nsIStartupCache* cache, nsACString &uri, + JSContext *cx, JSScript **scriptObj); + +nsresult +WriteCachedScript(nsIStartupCache* cache, nsACString &uri, + JSContext *cx, JSScript *scriptObj); +#endif /* mozJSLoaderUtils_h */ diff --git a/binary/src/subscriptLoader.cpp b/binary/src/subscriptLoader.cpp new file mode 100644 index 00000000..3b552a4a --- /dev/null +++ b/binary/src/subscriptLoader.cpp @@ -0,0 +1,479 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=4 sw=4 et tw=80: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert Ginda + * Kris Maglione + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * What follows is the ordinary mozIJSSubScriptLoader modified only to strip the + * useless, irritating, and troublesome "foo -> " prefixes from filenames. + */ + +#include "dactylUtils.h" +#include "mozJSLoaderUtils.h" + +#include "nsIServiceManager.h" +#include "nsIXPConnect.h" + +#include "nsIURI.h" +#include "nsIIOService.h" +#include "nsIChannel.h" +#include "nsIConsoleService.h" +#include "nsIScriptError.h" +#include "nsIInputStream.h" +#include "nsNetCID.h" +#include "nsAutoPtr.h" +#include "nsNetUtil.h" +#include "nsIProtocolHandler.h" +#include "nsIScriptSecurityManager.h" +#include "nsIFileURL.h" + +#include "jsapi.h" +#include "jscntxt.h" +#include "jsdbgapi.h" +#include "jsfriendapi.h" + +#include "mozilla/FunctionTimer.h" +#include "mozilla/scache/StartupCache.h" +#include "mozilla/scache/StartupCacheUtils.h" + +using namespace mozilla::scache; + +class nsACString_internal : nsACString {}; + +namespace mozilla { + namespace scache { + nsresult PathifyURI(nsIURI *in, nsACString_internal &out); + } +} + +/* load() error msgs, XXX localize? */ +#define LOAD_ERROR_NOSERVICE "Error creating IO Service." +#define LOAD_ERROR_NOURI "Error creating URI (invalid URL scheme?)" +#define LOAD_ERROR_NOSCHEME "Failed to get URI scheme. This is bad." +#define LOAD_ERROR_URI_NOT_LOCAL "Trying to load a non-local URI." +#define LOAD_ERROR_NOSTREAM "Error opening input stream (invalid filename?)" +#define LOAD_ERROR_NOCONTENT "ContentLength not available (not a local URL?)" +#define LOAD_ERROR_BADCHARSET "Error converting to specified charset" +#define LOAD_ERROR_BADREAD "File Read Error." +#define LOAD_ERROR_READUNDERFLOW "File Read Error (underflow.)" +#define LOAD_ERROR_NOPRINCIPALS "Failed to get principals." +#define LOAD_ERROR_NOSPEC "Failed to get URI spec. This is bad." + +// We just use the same reporter as the component loader +static void +mozJSLoaderErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep) +{ + nsresult rv; + + /* Use the console service to register the error. */ + nsCOMPtr consoleService = + do_GetService(NS_CONSOLESERVICE_CONTRACTID); + + /* + * Make an nsIScriptError, populate it with information from this + * error, then log it with the console service. The UI can then + * poll the service to update the Error console. + */ + nsCOMPtr errorObject = + do_CreateInstance(NS_SCRIPTERROR_CONTRACTID); + + if (consoleService && errorObject) { + /* + * Got an error object; prepare appropriate-width versions of + * various arguments to it. + */ + nsAutoString fileUni; + fileUni.Assign(NS_ConvertUTF8toUTF16(rep->filename)); + + PRUint32 column = rep->uctokenptr - rep->uclinebuf; + + rv = errorObject->Init(reinterpret_cast + (rep->ucmessage), + fileUni.get(), + reinterpret_cast + (rep->uclinebuf), + rep->lineno, column, rep->flags, + "component javascript"); + if (NS_SUCCEEDED(rv)) { + rv = consoleService->LogMessage(errorObject); + if (NS_SUCCEEDED(rv)) { + // We're done! Skip return to fall thru to stderr + // printout, for the benefit of those invoking the + // browser with -console + // return; + } + } + } + + /* + * If any of the above fails for some reason, fall back to + * printing to stderr. + */ +} + +static JSBool +Dump(JSContext *cx, uintN argc, jsval *vp) +{ + JSString *str; + if (!argc) + return JS_TRUE; + + str = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]); + if (!str) + return JS_FALSE; + + size_t length; + const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length); + if (!chars) + return JS_FALSE; + + fputs(NS_ConvertUTF16toUTF8(reinterpret_cast(chars)).get(), stderr); + return JS_TRUE; +} + +static nsresult +ReportError(JSContext *cx, const char *msg) +{ + JS_SetPendingException(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, msg))); + return NS_OK; +} + +static nsresult +ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj, + jschar *charset, const char *uriStr, + nsIIOService *serv, nsIPrincipal *principal, + JSScript **scriptObjp) +{ + nsCOMPtr chan; + nsCOMPtr instream; + JSPrincipals *jsPrincipals; + JSErrorReporter er; + + nsresult rv; + // Instead of calling NS_OpenURI, we create the channel ourselves and call + // SetContentType, to avoid expensive MIME type lookups (bug 632490). + rv = NS_NewChannel(getter_AddRefs(chan), uri, serv, + nsnull, nsnull, nsIRequest::LOAD_NORMAL); + if (NS_SUCCEEDED(rv)) { + chan->SetContentType(NS_LITERAL_CSTRING("application/javascript")); + rv = chan->Open(getter_AddRefs(instream)); + } + + if (NS_FAILED(rv)) { + return ReportError(cx, LOAD_ERROR_NOSTREAM); + } + + PRInt32 len = -1; + + rv = chan->GetContentLength(&len); + if (NS_FAILED(rv) || len == -1) { + return ReportError(cx, LOAD_ERROR_NOCONTENT); + } + + nsCString buf; + rv = NS_ReadInputStreamToString(instream, buf, len); + if (NS_FAILED(rv)) + return rv; + + /* we can't hold onto jsPrincipals as a module var because the + * JSPRINCIPALS_DROP macro takes a JSContext, which we won't have in the + * destructor */ + rv = principal->GetJSPrincipals(cx, &jsPrincipals); + if (NS_FAILED(rv) || !jsPrincipals) { + return ReportError(cx, LOAD_ERROR_NOPRINCIPALS); + } + + /* set our own error reporter so we can report any bad things as catchable + * exceptions, including the source/line number */ + er = JS_SetErrorReporter(cx, mozJSLoaderErrorReporter); + + if (charset) { + nsString script; + rv = nsScriptLoader::ConvertToUTF16( + nsnull, reinterpret_cast(buf.get()), len, + nsDependentString(reinterpret_cast(charset)), nsnull, script); + + if (NS_FAILED(rv)) { + JSPRINCIPALS_DROP(cx, jsPrincipals); + return ReportError(cx, LOAD_ERROR_BADCHARSET); + } + + *scriptObjp = + JS_CompileUCScriptForPrincipals(cx, target_obj, jsPrincipals, + reinterpret_cast(script.get()), + script.Length(), uriStr, 1); + } else { + *scriptObjp = + JS_CompileScriptForPrincipals(cx, target_obj, jsPrincipals, buf.get(), + len, uriStr, 1); + } + + JSPRINCIPALS_DROP(cx, jsPrincipals); + + /* repent for our evil deeds */ + JS_SetErrorReporter(cx, er); + + return NS_OK; +} + +NS_IMETHODIMP /* args and return value are delt with using XPConnect and JSAPI */ +dactylUtils::LoadSubScript (const PRUnichar * aURL + /* [, JSObject *target_obj] */) +{ + /* + * Loads a local url and evals it into the current cx + * Synchronous (an async version would be cool too.) + * url: The url to load. Must be local so that it can be loaded + * synchronously. + * target_obj: Optional object to eval the script onto (defaults to context + * global) + * returns: Whatever jsval the script pointed to by the url returns. + * Should ONLY (O N L Y !) be called from JavaScript code. + */ + + /* gotta define most of this stuff up here because of all the gotos, + * defined the rest up here to be consistent */ + nsresult rv; + JSBool ok; + +#ifdef NS_FUNCTION_TIMER + NS_TIME_FUNCTION_FMT("%s (line %d) (url: %s)", MOZ_FUNCTION_NAME, + __LINE__, NS_LossyConvertUTF16toASCII(aURL).get()); +#else + (void)aURL; // prevent compiler warning +#endif + + /* get JS things from the CallContext */ + nsCOMPtr xpc = do_GetService(nsIXPConnect::GetCID()); + if (!xpc) return NS_ERROR_FAILURE; + + nsAXPCNativeCallContext *cc = nsnull; + rv = xpc->GetCurrentNativeCallContext(&cc); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + JSContext *cx; + rv = cc->GetJSContext (&cx); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + PRUint32 argc; + rv = cc->GetArgc (&argc); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + jsval *argv; + rv = cc->GetArgvPtr (&argv); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + jsval *rval; + rv = cc->GetRetValPtr (&rval); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + /* set mJSPrincipals if it's not here already */ + if (!mSystemPrincipal) + { + nsCOMPtr secman = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + if (!secman) + return rv; + + rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal)); + if (NS_FAILED(rv) || !mSystemPrincipal) + return rv; + } + + JSAutoRequest ar(cx); + + JSString *url; + JSObject *target_obj = nsnull; + jschar *charset = nsnull; + ok = JS_ConvertArguments (cx, argc, argv, "S / o W", &url, &target_obj, &charset); + if (!ok) + { + /* let the exception raised by JS_ConvertArguments show through */ + return NS_OK; + } + + JSAutoByteString urlbytes(cx, url); + if (!urlbytes) + { + return NS_OK; + } + + if (!target_obj) + { + /* if the user didn't provide an object to eval onto, find the global + * object by walking the parent chain of the calling object */ + + nsCOMPtr wn; + rv = cc->GetCalleeWrapper (getter_AddRefs(wn)); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + rv = wn->GetJSObject (&target_obj); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + + JSObject *maybe_glob = JS_GetParent (cx, target_obj); + while (maybe_glob != nsnull) + { + target_obj = maybe_glob; + maybe_glob = JS_GetParent (cx, maybe_glob); + } + } + + // Remember an object out of the calling compartment so that we + // can properly wrap the result later. + nsCOMPtr principal = mSystemPrincipal; + JSObject *result_obj = target_obj; + target_obj = JS_FindCompilationScope(cx, target_obj); + if (!target_obj) + return NS_ERROR_FAILURE; + + if (target_obj != result_obj) + { + nsCOMPtr secman = + do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID); + if (!secman) + return NS_ERROR_FAILURE; + + rv = secman->GetObjectPrincipal(cx, target_obj, getter_AddRefs(principal)); + NS_ENSURE_SUCCESS(rv, rv); + } + + JSAutoEnterCompartment ac; + if (!ac.enter(cx, target_obj)) + return NS_ERROR_UNEXPECTED; + + /* load up the url. From here on, failures are reflected as ``custom'' + * js exceptions */ + nsCOMPtr uri; + nsCAutoString uriStr; + nsCAutoString scheme; + + JSStackFrame* frame = nsnull; + JSScript* script = nsnull; + + // Figure out who's calling us + do + { + frame = JS_FrameIterator(cx, &frame); + + if (frame) + script = JS_GetFrameScript(cx, frame); + } while (frame && !script); + + if (!script) + { + // No script means we don't know who's calling, bail. + + return NS_ERROR_FAILURE; + } + + nsCOMPtr serv = do_GetService(NS_IOSERVICE_CONTRACTID); + if (!serv) { + return ReportError(cx, LOAD_ERROR_NOSERVICE); + } + + // Make sure to explicitly create the URI, since we'll need the + // canonicalized spec. + rv = NS_NewURI(getter_AddRefs(uri), urlbytes.ptr(), nsnull, serv); + if (NS_FAILED(rv)) { + return ReportError(cx, LOAD_ERROR_NOURI); + } + + rv = uri->GetSpec(uriStr); + if (NS_FAILED(rv)) { + return ReportError(cx, LOAD_ERROR_NOSPEC); + } + + rv = uri->GetScheme(scheme); + if (NS_FAILED(rv)) { + return ReportError(cx, LOAD_ERROR_NOSCHEME); + } + + bool writeScript = false; + JSScript *scriptObj = nsnull; + JSVersion version = cx->findVersion(); + + nsCAutoString cachePath; + cachePath.Append("jssubloader/"); + cachePath.Append(version); + + if (false) + // This is evil. Very evil. Unfortunately, the PathifyURI symbol is + // exported, but with an argument type that we don't have access to. + PathifyURI(uri, *(nsACString_internal*)&cachePath); + else { + cachePath.Append("/"); + cachePath.Append(uriStr); + } + + // Suppress caching if we're compiling as content. + nsCOMPtr cache; + if (mSystemPrincipal) { + cache = do_GetService("@mozilla.org/startupcache/cache;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + rv = ReadCachedScript(cache, cachePath, cx, &scriptObj); + } + + if (!scriptObj) { + rv = ReadScript(uri, cx, target_obj, charset, (char *)uriStr.get(), serv, + principal, &scriptObj); + writeScript = true; + } + + if (NS_FAILED(rv) || !scriptObj) + return rv; + + ok = false; + if (scriptObj) + ok = JS_ExecuteScriptVersion(cx, target_obj, scriptObj, rval, version); + + if (ok) { + JSAutoEnterCompartment rac; + if (!rac.enter(cx, result_obj) || !JS_WrapValue(cx, rval)) + return NS_ERROR_UNEXPECTED; + } + + if (cache && ok && writeScript) { + WriteCachedScript(cache, cachePath, cx, scriptObj); + } + + cc->SetReturnValueWasSet (ok); + return NS_OK; +} + diff --git a/common/modules/commands.jsm b/common/modules/commands.jsm index 0fb9a065..0759d151 100644 --- a/common/modules/commands.jsm +++ b/common/modules/commands.jsm @@ -509,7 +509,8 @@ var CommandHive = Class("CommandHive", Contexts.Hive, { let closure = function () self._map[name]; memoize(this._map, name, function () commands.Command(specs, description, action, extra)); - memoize(this._list, this._list.length, closure); + if (!extra.hidden) + memoize(this._list, this._list.length, closure); for (let alias in values(names.slice(1))) memoize(this._map, alias, closure); @@ -1404,9 +1405,11 @@ var Commands = Module("commands", { const { commands, contexts } = modules; commands.add(["(", "-("], "", - function (args) { dactyl.echoerr(_("dactyl.cheerUp")); }); + function (args) { dactyl.echoerr(_("dactyl.cheerUp")); }, + { hidden: true }); commands.add([")", "-)"], "", - function (args) { dactyl.echoerr(_("dactyl.somberDown")); }); + function (args) { dactyl.echoerr(_("dactyl.somberDown")); }, + { hidden: true }); commands.add(["com[mand]"], "List or define commands", diff --git a/common/modules/io.jsm b/common/modules/io.jsm index b9d3fb8a..e724ab6d 100644 --- a/common/modules/io.jsm +++ b/common/modules/io.jsm @@ -344,7 +344,7 @@ var IO = Module("io", { return uri; let channel = services.io.newChannelFromURI(uri); - channel.cancel(Cr.NS_BINDING_ABORTED); + try { channel.cancel(Cr.NS_BINDING_ABORTED); } catch (e) {} if (channel instanceof Ci.nsIJARChannel) return channel.URI.QueryInterface(Ci.nsIJARURI); } diff --git a/common/modules/overlay.jsm b/common/modules/overlay.jsm index 6cb81718..e4e23911 100644 --- a/common/modules/overlay.jsm +++ b/common/modules/overlay.jsm @@ -290,7 +290,7 @@ var Overlay = Module("Overlay", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReferen * property in *overrides* is added to *object*, replacing any * original value. Functions in *overrides* are augmented with the * new properties *super*, *supercall*, and *superapply*, in the - * same manner as class methods, so that they man call their + * same manner as class methods, so that they may call their * overridden counterparts. * * @param {object} object The object to overlay. diff --git a/common/modules/services.jsm b/common/modules/services.jsm index b69522c0..ba007dfa 100644 --- a/common/modules/services.jsm +++ b/common/modules/services.jsm @@ -33,6 +33,7 @@ var Services = Module("Services", { this.add("clipboardHelper", "@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper"); this.add("commandLineHandler", "@mozilla.org/commandlinehandler/general-startup;1?type=dactyl"); this.add("console", "@mozilla.org/consoleservice;1", "nsIConsoleService"); + this.add("dactyl", "@dactyl.googlecode.com/extra/utils", "dactylIUtils"); this.add("dactyl:", "@mozilla.org/network/protocol;1?name=dactyl"); this.add("debugger", "@mozilla.org/js/jsd/debugger-service;1", "jsdIDebuggerService"); this.add("directory", "@mozilla.org/file/directory_service;1", "nsIProperties"); diff --git a/common/modules/util.jsm b/common/modules/util.jsm index 3ee24e34..22ce3a97 100644 --- a/common/modules/util.jsm +++ b/common/modules/util.jsm @@ -636,7 +636,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]), return File(uri); let channel = services.io.newChannelFromURI(uri); - channel.cancel(Cr.NS_BINDING_ABORTED); + try { channel.cancel(Cr.NS_BINDING_ABORTED); } catch (e) {} if (channel instanceof Ci.nsIFileChannel) return File(channel.file); }