mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 407216 - DOM quick stubs - faster paths for top N DOM methods (r+sr=jst, security r=mrbkap, build r=bsmedberg)
* * * * * *
This commit is contained in:
parent
6b04323552
commit
fe99024391
@ -64,7 +64,6 @@
|
||||
#ifndef WINABLEAPI
|
||||
#include <winable.h>
|
||||
#endif
|
||||
#undef ERROR /// Otherwise we can't include nsIDOMNSEvent.h if we include this
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsICrashReporter.h"
|
||||
#endif
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "domstubs.idl"
|
||||
|
||||
%{C++
|
||||
#ifdef WINCE
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
%}
|
||||
|
@ -3823,7 +3823,8 @@ nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper,
|
||||
// be calling nsWindowSH::GlobalResolve directly.
|
||||
JSObject *global = ::JS_GetGlobalForObject(cx, obj);
|
||||
jsval val;
|
||||
if (!::JS_LookupProperty(cx, global, mData->mName, &val)) {
|
||||
if (!::JS_LookupPropertyWithFlags(cx, global, mData->mName,
|
||||
JSRESOLVE_CLASSNAME, &val)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
@ -4059,6 +4060,25 @@ nsDOMClassInfo::InnerObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * proto)
|
||||
{
|
||||
PRUint32 flags = (mData->mScriptableFlags & DONT_ENUM_STATIC_PROPS)
|
||||
? 0
|
||||
: JSPROP_ENUMERATE;
|
||||
|
||||
PRUint32 count = 0;
|
||||
while (mData->mInterfaces[count]) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!sXPConnect->DefineDOMQuickStubs(cx, proto, flags,
|
||||
count, mData->mInterfaces)) {
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIClassInfo *
|
||||
NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
|
||||
|
@ -982,7 +982,7 @@ typedef enum JSErrNum {
|
||||
JSErr_Limit
|
||||
} JSErrNum;
|
||||
|
||||
extern const JSErrorFormatString *
|
||||
extern JS_FRIEND_API(const JSErrorFormatString *)
|
||||
js_GetErrorMessage(void *userRef, const char *locale, const uintN errorNumber);
|
||||
|
||||
#ifdef va_start
|
||||
|
@ -55,7 +55,7 @@
|
||||
* to *_retval unless they want to return PR_FALSE.
|
||||
*/
|
||||
|
||||
[uuid(1455f6fe-6de9-4b62-a2b3-d1aee82dd829)]
|
||||
[uuid(5d309b93-e9b4-4374-bcd5-44245c83408f)]
|
||||
interface nsIXPCScriptable : nsISupports
|
||||
{
|
||||
/* bitflags used for 'flags' (only 32 bits available!) */
|
||||
@ -174,4 +174,8 @@ interface nsIXPCScriptable : nsISupports
|
||||
|
||||
JSObjectPtr innerObject(in nsIXPConnectWrappedNative wrapper,
|
||||
in JSContextPtr cx, in JSObjectPtr obj);
|
||||
|
||||
// This method is called if the WANT_POSTCREATE bit is set in
|
||||
// scriptableFlags.
|
||||
void postCreatePrototype(in JSContextPtr cx, in JSObjectPtr proto);
|
||||
};
|
||||
|
@ -405,7 +405,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
|
||||
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
|
||||
%}
|
||||
|
||||
[uuid(c1d4a482-1beb-4c82-9c0b-d2ab93acc7ef)]
|
||||
[uuid(d4c6bc06-2a4f-4315-90ec-d12904aca046)]
|
||||
interface nsIXPConnect : nsISupports
|
||||
{
|
||||
%{ C++
|
||||
@ -747,4 +747,28 @@ interface nsIXPConnect : nsISupports
|
||||
* passed here.
|
||||
*/
|
||||
void setReportAllJSExceptions(in boolean reportAllJSExceptions);
|
||||
|
||||
/**
|
||||
* Define quick stubs on the given object, @a proto.
|
||||
*
|
||||
* @param cx
|
||||
* A context. Requires request.
|
||||
* @param proto
|
||||
* The (newly created) prototype object for a DOM class. The JS half
|
||||
* of an XPCWrappedNativeProto.
|
||||
* @param flags
|
||||
* Property flags for the quick stub properties--should be either
|
||||
* JSPROP_ENUMERATE or 0.
|
||||
* @param interfaceCount
|
||||
* The number of interfaces the class implements.
|
||||
* @param interfaceArray
|
||||
* The interfaces the class implements; interfaceArray and
|
||||
* interfaceCount are like what nsIClassInfo.getInterfaces returns.
|
||||
*/
|
||||
[noscript,notxpcom] PRBool defineDOMQuickStubs(
|
||||
in JSContextPtr cx,
|
||||
in JSObjectPtr proto,
|
||||
in PRUint32 flags,
|
||||
in PRUint32 interfaceCount,
|
||||
[array, size_is(interfaceCount)] in nsIIDPtr interfaceArray);
|
||||
};
|
||||
|
@ -232,6 +232,11 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper,
|
||||
{NS_ERROR("never called"); return NS_ERROR_NOT_IMPLEMENTED;}
|
||||
#endif
|
||||
|
||||
#ifndef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
|
||||
NS_IMETHODIMP XPC_MAP_CLASSNAME::PostCreatePrototype(JSContext *cx, JSObject *proto)
|
||||
{return NS_OK;}
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
#undef XPC_MAP_CLASSNAME
|
||||
@ -313,6 +318,10 @@ NS_IMETHODIMP XPC_MAP_CLASSNAME::InnerObject(nsIXPConnectWrappedNative *wrapper,
|
||||
#undef XPC_MAP_WANT_OUTER_OBJECT
|
||||
#endif
|
||||
|
||||
#ifdef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
|
||||
#undef XPC_MAP_WANT_POST_CREATE_PROTOTYPE
|
||||
#endif
|
||||
|
||||
#ifdef XPC_MAP_FLAGS
|
||||
#undef XPC_MAP_FLAGS
|
||||
#endif
|
||||
|
@ -67,6 +67,18 @@ REQUIRES = xpcom \
|
||||
dom \
|
||||
$(NULL)
|
||||
|
||||
# These modules are required because the auto-generated file
|
||||
# dom_quickstubs.cpp #includes header files from many places.
|
||||
REQUIRES += content \
|
||||
editor \
|
||||
layout \
|
||||
rdf \
|
||||
svg \
|
||||
xuldoc \
|
||||
xultmpl \
|
||||
$(NULL)
|
||||
|
||||
|
||||
CPPSRCS = \
|
||||
nsScriptError.cpp \
|
||||
nsXPConnect.cpp \
|
||||
@ -99,6 +111,8 @@ CPPSRCS = \
|
||||
XPCSafeJSObjectWrapper.cpp \
|
||||
XPCCrossOriginWrapper.cpp \
|
||||
XPCWrapper.cpp \
|
||||
xpcquickstubs.cpp \
|
||||
dom_quickstubs.cpp \
|
||||
$(NULL)
|
||||
ifdef XPC_IDISPATCH_SUPPORT
|
||||
CPPSRCS += XPCDispObject.cpp \
|
||||
@ -168,3 +182,25 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
nsXPConnect.$(OBJ_SUFFIX): dom_quickstubs.h
|
||||
|
||||
dom_quickstubs.h dom_quickstubs.cpp: $(srcdir)/dom_quickstubs.qsconf \
|
||||
$(srcdir)/qsgen.py \
|
||||
$(topsrcdir)/xpcom/idl-parser/header.py \
|
||||
$(topsrcdir)/xpcom/idl-parser/xpidl.py
|
||||
PYTHONPATH=$(topsrcdir)/xpcom/idl-parser \
|
||||
$(PYTHON) $(srcdir)/qsgen.py \
|
||||
--idlpath=$(DEPTH)/dist/idl \
|
||||
--cachedir=$(DEPTH)/xpcom/idl-parser \
|
||||
--header-output dom_quickstubs.h \
|
||||
--stub-output dom_quickstubs.cpp \
|
||||
--makedepend-output dom_quickstubs.depends \
|
||||
$(srcdir)/dom_quickstubs.qsconf
|
||||
|
||||
GARBAGE += \
|
||||
dom_quickstubs.h \
|
||||
dom_quickstubs.cpp \
|
||||
dom_quickstubs.depends \
|
||||
$(NULL)
|
||||
|
||||
-include dom_quickstubs.depends
|
||||
|
545
js/src/xpconnect/src/dom_quickstubs.qsconf
Normal file
545
js/src/xpconnect/src/dom_quickstubs.qsconf
Normal file
@ -0,0 +1,545 @@
|
||||
# -*- Mode: Python -*-
|
||||
# ***** 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 code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Jason Orendorff <jorendorff@mozilla.com>
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
name = 'DOM'
|
||||
|
||||
# A quick warning:
|
||||
#
|
||||
# Attributes or methods that call GetCurrentNativeCallContext must not be
|
||||
# quick-stubbed, because quick stubs don't generate a native call context.
|
||||
# qsgen.py has no way of knowing which attributes and methods do this, as it
|
||||
# looks at interfaces, not implementations. The symptoms, if you quick-stub
|
||||
# one of those, can be really weird, because GetCurrentNativeCallContext
|
||||
# doesn't crash--it may in fact return a plausible wrong answer.
|
||||
|
||||
members = [
|
||||
# dom/public/idl/base
|
||||
#
|
||||
# Note that many implementations of interfaces in this directory
|
||||
# use GetCurrentNativeCallContext, notably:
|
||||
# - nsIDOMCrypto.{generateCRMFRequest,signText}
|
||||
# - nsIDOMLocation.reload
|
||||
# - nsIDOMNSHistory.go
|
||||
# - nsIDOMJSNavigator.preference
|
||||
# - nsIDOMJSPluginArray.refresh
|
||||
# - nsIDOMWindowInternal.postMessage
|
||||
# - nsIDOMJSWindow.{prompt,setTimeout,setInterval,open,openDialog}
|
||||
#
|
||||
# (And nsIDOMModalContentWindow.returnValue is an attribute of type
|
||||
# nsIVariant, which qsgen.py can't handle.)
|
||||
#
|
||||
'nsIDOMWindow.name',
|
||||
'nsIDOMWindow.parent',
|
||||
'nsIDOMWindow.top',
|
||||
'nsIDOMWindow.document',
|
||||
'nsIDOMWindow.getSelection',
|
||||
'nsIDOMWindowCollection.item',
|
||||
'nsIDOMWindowCollection.length',
|
||||
'nsIDOMLocation.hostname',
|
||||
'nsIDOMLocation.href',
|
||||
'nsIDOMScreen.top',
|
||||
'nsIDOMScreen.height',
|
||||
'nsIDOMScreen.width',
|
||||
'nsIDOMScreen.left',
|
||||
'nsIDOMClientRect.top',
|
||||
'nsIDOMClientRect.right',
|
||||
'nsIDOMClientRect.bottom',
|
||||
'nsIDOMClientRect.left',
|
||||
'nsIDOMClientRectList.item',
|
||||
'nsIDOMClientRectList.length',
|
||||
|
||||
# dom/public/idl/canvas
|
||||
#
|
||||
# nsIDOMCanvasRenderingContext2D
|
||||
# NOTE: attributes strokeStyle and fillStyle are nsIVariant
|
||||
# NOTE: drawImage(), getImageData(), and putImageData() use
|
||||
# GetCurrentNativeCallContext
|
||||
'nsIDOMCanvasRenderingContext2D.canvas',
|
||||
'nsIDOMCanvasRenderingContext2D.save',
|
||||
'nsIDOMCanvasRenderingContext2D.restore',
|
||||
'nsIDOMCanvasRenderingContext2D.scale',
|
||||
'nsIDOMCanvasRenderingContext2D.rotate',
|
||||
'nsIDOMCanvasRenderingContext2D.translate',
|
||||
'nsIDOMCanvasRenderingContext2D.transform',
|
||||
'nsIDOMCanvasRenderingContext2D.setTransform',
|
||||
'nsIDOMCanvasRenderingContext2D.globalAlpha',
|
||||
'nsIDOMCanvasRenderingContext2D.globalCompositeOperation',
|
||||
'nsIDOMCanvasRenderingContext2D.lineWidth',
|
||||
'nsIDOMCanvasRenderingContext2D.lineCap',
|
||||
'nsIDOMCanvasRenderingContext2D.lineJoin',
|
||||
'nsIDOMCanvasRenderingContext2D.miterLimit',
|
||||
'nsIDOMCanvasRenderingContext2D.clearRect',
|
||||
'nsIDOMCanvasRenderingContext2D.fillRect',
|
||||
'nsIDOMCanvasRenderingContext2D.strokeRect',
|
||||
'nsIDOMCanvasRenderingContext2D.beginPath',
|
||||
'nsIDOMCanvasRenderingContext2D.closePath',
|
||||
'nsIDOMCanvasRenderingContext2D.moveTo',
|
||||
'nsIDOMCanvasRenderingContext2D.lineTo',
|
||||
'nsIDOMCanvasRenderingContext2D.quadraticCurveTo',
|
||||
'nsIDOMCanvasRenderingContext2D.bezierCurveTo',
|
||||
'nsIDOMCanvasRenderingContext2D.arcTo',
|
||||
'nsIDOMCanvasRenderingContext2D.arc',
|
||||
'nsIDOMCanvasRenderingContext2D.rect',
|
||||
'nsIDOMCanvasRenderingContext2D.fill',
|
||||
'nsIDOMCanvasRenderingContext2D.stroke',
|
||||
'nsIDOMCanvasRenderingContext2D.clip',
|
||||
'nsIDOMCanvasRenderingContext2D.font',
|
||||
'nsIDOMCanvasRenderingContext2D.textAlign',
|
||||
'nsIDOMCanvasRenderingContext2D.textBaseline',
|
||||
'nsIDOMCanvasRenderingContext2D.fillText',
|
||||
'nsIDOMCanvasRenderingContext2D.strokeText',
|
||||
'nsIDOMCanvasRenderingContext2D.measureText',
|
||||
'nsIDOMCanvasRenderingContext2D.isPointInPath',
|
||||
'nsIDOMTextMetrics.width',
|
||||
|
||||
# dom/public/idl/core
|
||||
'nsIDOMCharacterData.data',
|
||||
'nsIDOMCharacterData.length',
|
||||
'nsIDOMDocument.documentElement',
|
||||
'nsIDOMDocument.implementation',
|
||||
'nsIDOMDocument.getElementsByTagName',
|
||||
'nsIDOMDocument.doctype',
|
||||
'nsIDOMDocument.getElementsByTagNameNS',
|
||||
'nsIDOMDocument.getElementById',
|
||||
'nsIDOMDocument.createDocumentFragment',
|
||||
'nsIDOMDocument.createElement',
|
||||
'nsIDOMDocument.importNode',
|
||||
'nsIDOMDocument.createTextNode',
|
||||
'nsIDOMElement.removeAttributeNS',
|
||||
'nsIDOMElement.removeAttribute',
|
||||
'nsIDOMElement.getAttribute',
|
||||
'nsIDOMElement.getElementsByTagName',
|
||||
'nsIDOMElement.setAttribute',
|
||||
'nsIDOMElement.getElementsByTagNameNS',
|
||||
'nsIDOMElement.hasAttributeNS',
|
||||
'nsIDOMElement.tagName',
|
||||
'nsIDOMElement.setAttributeNS',
|
||||
'nsIDOMElement.hasAttribute',
|
||||
'nsIDOMElement.getAttributeNS',
|
||||
'nsIDOMNamedNodeMap.item',
|
||||
'nsIDOMNamedNodeMap.length',
|
||||
'nsIDOMNode.appendChild',
|
||||
'nsIDOMNode.nextSibling',
|
||||
'nsIDOMNode.cloneNode',
|
||||
'nsIDOMNode.firstChild',
|
||||
'nsIDOMNode.prefix',
|
||||
'nsIDOMNode.nodeValue',
|
||||
'nsIDOMNode.childNodes',
|
||||
'nsIDOMNode.normalize',
|
||||
'nsIDOMNode.nodeName',
|
||||
'nsIDOMNode.namespaceURI',
|
||||
'nsIDOMNode.hasChildNodes',
|
||||
'nsIDOMNode.previousSibling',
|
||||
'nsIDOMNode.nodeType',
|
||||
'nsIDOMNode.insertBefore',
|
||||
'nsIDOMNode.replaceChild',
|
||||
'nsIDOMNode.localName',
|
||||
'nsIDOMNode.lastChild',
|
||||
'nsIDOMNode.ownerDocument',
|
||||
'nsIDOMNode.parentNode',
|
||||
'nsIDOMNode.removeChild',
|
||||
'nsIDOMNode.hasAttributes',
|
||||
'nsIDOMNode.attributes',
|
||||
'nsIDOMNodeList.item',
|
||||
'nsIDOMNodeList.length',
|
||||
'nsIDOMText.splitText',
|
||||
'nsIDOM3Document.documentURI',
|
||||
'nsIDOM3Document.adoptNode',
|
||||
'nsIDOM3Document.renameNode',
|
||||
'nsIDOM3Node.compareDocumentPosition',
|
||||
'nsIDOM3Node.getUserData',
|
||||
'nsIDOM3Node.baseURI',
|
||||
'nsIDOM3Node.textContent',
|
||||
'nsIDOM3Node.isSameNode',
|
||||
'nsIDOM3Node.lookupNamespaceURI',
|
||||
'nsIDOM3Node.setUserData',
|
||||
'nsIDOM3Node.lookupPrefix',
|
||||
'nsIDOM3Node.isDefaultNamespace',
|
||||
'nsIDOM3Node.isEqualNode',
|
||||
'nsIDOM3Text.isElementContentWhitespace',
|
||||
'nsIDOM3Text.replaceWholeText',
|
||||
'nsIDOM3Text.wholeText',
|
||||
'nsIDOMDOMStringList.item',
|
||||
'nsIDOMDOMStringList.length',
|
||||
'nsIDOMDOMStringList.contains',
|
||||
'nsIDOMNameList.getName',
|
||||
'nsIDOMNameList.contains',
|
||||
'nsIDOMNameList.containsNS',
|
||||
'nsIDOMNameList.length',
|
||||
'nsIDOMNameList.getNamespaceURI',
|
||||
'nsIDOMNSDocument.getElementsByClassName',
|
||||
'nsIDOMNSDocument.title',
|
||||
'nsIDOMNSDocument.hasFocus',
|
||||
'nsIDOMNSDocument.location',
|
||||
'nsIDOMNSDocument.elementFromPoint',
|
||||
'nsIDOMNSDocument.activeElement',
|
||||
'nsIDOMNSDocument.getBoxObjectFor',
|
||||
'nsIDOMXMLDocument.evaluateXPointer',
|
||||
'nsIDOMXMLDocument.evaluateFIXptr',
|
||||
'nsIDOMNSEditableElement.editor',
|
||||
'nsIDOMNSEditableElement.setUserInput',
|
||||
'nsIDOMNSElement.getClientRects',
|
||||
'nsIDOMNSElement.getBoundingClientRect',
|
||||
'nsIDOMNSElement.getElementsByClassName',
|
||||
'nsIDOMNSElement.scrollWidth',
|
||||
'nsIDOMNSElement.clientLeft',
|
||||
'nsIDOMNSElement.clientHeight',
|
||||
'nsIDOMNSElement.clientWidth',
|
||||
'nsIDOMNSElement.clientTop',
|
||||
|
||||
# dom/public/idl/css
|
||||
'nsIDOMElementCSSInlineStyle.style',
|
||||
'nsIDOMCSS2Properties.background',
|
||||
'nsIDOMCSS2Properties.height',
|
||||
'nsIDOMCSS2Properties.textAlign',
|
||||
'nsIDOMCSS2Properties.right',
|
||||
'nsIDOMCSS2Properties.bottom',
|
||||
'nsIDOMCSS2Properties.fontSize',
|
||||
'nsIDOMCSS2Properties.backgroundColor',
|
||||
'nsIDOMCSS2Properties.letterSpacing',
|
||||
'nsIDOMCSS2Properties.verticalAlign',
|
||||
'nsIDOMCSS2Properties.color',
|
||||
'nsIDOMCSS2Properties.top',
|
||||
'nsIDOMCSS2Properties.width',
|
||||
'nsIDOMCSS2Properties.display',
|
||||
'nsIDOMCSS2Properties.zIndex',
|
||||
'nsIDOMCSS2Properties.position',
|
||||
'nsIDOMCSS2Properties.left',
|
||||
'nsIDOMCSS2Properties.visibility',
|
||||
'nsIDOMNSCSS2Properties.opacity',
|
||||
'nsIDOMRect.top',
|
||||
'nsIDOMRect.right',
|
||||
'nsIDOMRect.left',
|
||||
'nsIDOMRect.bottom',
|
||||
'nsIDOMViewCSS.getComputedStyle',
|
||||
|
||||
# dom/public/idl/events
|
||||
'nsIDOMEvent.target',
|
||||
'nsIDOMEvent.preventDefault',
|
||||
'nsIDOMEvent.cancelable',
|
||||
'nsIDOMEvent.currentTarget',
|
||||
'nsIDOMEvent.timeStamp',
|
||||
'nsIDOMEvent.bubbles',
|
||||
'nsIDOMEvent.type',
|
||||
'nsIDOMEvent.initEvent',
|
||||
'nsIDOMEvent.stopPropagation',
|
||||
'nsIDOMEvent.eventPhase',
|
||||
'nsIDOMEventTarget.dispatchEvent',
|
||||
'nsIDOMEventTarget.removeEventListener',
|
||||
'nsIDOMEventTarget.addEventListener',
|
||||
'nsIDOMEventListener.handleEvent',
|
||||
'nsIDOMCustomEvent.setCurrentTarget',
|
||||
'nsIDOMCustomEvent.setEventPhase',
|
||||
'nsIDOMDocumentEvent.createEvent',
|
||||
'nsIDOMMouseEvent.clientX',
|
||||
'nsIDOMMouseEvent.clientY',
|
||||
'nsIDOMMouseEvent.relatedTarget',
|
||||
'nsIDOMMouseEvent.shiftKey',
|
||||
'nsIDOMMouseEvent.button',
|
||||
'nsIDOMMouseEvent.altKey',
|
||||
'nsIDOMMouseEvent.metaKey',
|
||||
'nsIDOMMouseEvent.ctrlKey',
|
||||
'nsIDOMMouseEvent.screenY',
|
||||
'nsIDOMMouseEvent.screenX',
|
||||
'nsIDOMNSEvent.originalTarget',
|
||||
'nsIDOMNSEvent.preventCapture',
|
||||
'nsIDOMKeyEvent.ctrlKey',
|
||||
'nsIDOMKeyEvent.shiftKey',
|
||||
'nsIDOMKeyEvent.keyCode',
|
||||
'nsIDOMKeyEvent.metaKey',
|
||||
'nsIDOMKeyEvent.charCode',
|
||||
'nsIDOMKeyEvent.altKey',
|
||||
'nsIDOMMutationEvent.attrName',
|
||||
'nsIDOMMutationEvent.relatedNode',
|
||||
'nsIDOMMutationEvent.attrChange',
|
||||
'nsIDOMMutationEvent.newValue',
|
||||
'nsIDOMMutationEvent.prevValue',
|
||||
'nsIDOMNSUIEvent.getPreventDefault',
|
||||
'nsIDOMNSUIEvent.which',
|
||||
'nsIDOMNSUIEvent.rangeParent',
|
||||
'nsIDOMNSUIEvent.rangeOffset',
|
||||
'nsIDOMNSUIEvent.pageX',
|
||||
'nsIDOMNSUIEvent.pageY',
|
||||
'nsIDOMNSUIEvent.isChar',
|
||||
|
||||
# dom/public/idl/geolocation - None.
|
||||
|
||||
# dom/public/idl/html
|
||||
'nsIDOMHTMLAnchorElement.href',
|
||||
'nsIDOMHTMLAnchorElement.rel',
|
||||
'nsIDOMHTMLAnchorElement.target',
|
||||
'nsIDOMHTMLBaseElement.href',
|
||||
'nsIDOMHTMLBaseElement.target',
|
||||
'nsIDOMHTMLButtonElement.name',
|
||||
'nsIDOMHTMLButtonElement.form',
|
||||
'nsIDOMHTMLButtonElement.value',
|
||||
'nsIDOMHTMLButtonElement.disabled',
|
||||
'nsIDOMHTMLCollection.item',
|
||||
'nsIDOMHTMLCollection.length',
|
||||
'nsIDOMHTMLDocument.body',
|
||||
'nsIDOMHTMLDocument.getElementsByName',
|
||||
'nsIDOMHTMLDocument.anchors',
|
||||
'nsIDOMHTMLDocument.links',
|
||||
'nsIDOMHTMLDocument.title',
|
||||
'nsIDOMHTMLDocument.URL',
|
||||
'nsIDOMHTMLDocument.referrer',
|
||||
'nsIDOMHTMLDocument.forms',
|
||||
'nsIDOMHTMLDocument.cookie',
|
||||
'nsIDOMHTMLDocument.images',
|
||||
'nsIDOMHTMLDocument.close',
|
||||
'nsIDOMHTMLElement.className',
|
||||
'nsIDOMHTMLElement.id',
|
||||
'nsIDOMHTMLElement.title',
|
||||
'nsIDOMHTMLFormElement.elements',
|
||||
'nsIDOMHTMLFormElement.name',
|
||||
'nsIDOMHTMLFormElement.submit',
|
||||
'nsIDOMHTMLFormElement.length',
|
||||
'nsIDOMHTMLFormElement.target',
|
||||
'nsIDOMHTMLFormElement.action',
|
||||
'nsIDOMHTMLFrameElement.src',
|
||||
'nsIDOMHTMLFrameElement.contentDocument',
|
||||
'nsIDOMHTMLFrameElement.name',
|
||||
'nsIDOMHTMLFrameSetElement.rows',
|
||||
'nsIDOMHTMLFrameSetElement.cols',
|
||||
'nsIDOMHTMLIFrameElement.src',
|
||||
'nsIDOMHTMLIFrameElement.contentDocument',
|
||||
'nsIDOMHTMLImageElement.src',
|
||||
'nsIDOMHTMLImageElement.name',
|
||||
'nsIDOMHTMLImageElement.height',
|
||||
'nsIDOMHTMLImageElement.width',
|
||||
'nsIDOMHTMLInputElement.defaultChecked',
|
||||
'nsIDOMHTMLInputElement.disabled',
|
||||
'nsIDOMHTMLInputElement.select',
|
||||
'nsIDOMHTMLInputElement.checked',
|
||||
'nsIDOMHTMLInputElement.type',
|
||||
'nsIDOMHTMLInputElement.form',
|
||||
'nsIDOMHTMLInputElement.src',
|
||||
'nsIDOMHTMLInputElement.name',
|
||||
'nsIDOMHTMLInputElement.value',
|
||||
'nsIDOMHTMLLinkElement.disabled',
|
||||
'nsIDOMHTMLOptionElement.index',
|
||||
'nsIDOMHTMLOptionElement.selected',
|
||||
'nsIDOMHTMLOptionElement.form',
|
||||
'nsIDOMHTMLOptionElement.text',
|
||||
'nsIDOMHTMLOptionElement.defaultSelected',
|
||||
'nsIDOMHTMLOptionElement.value',
|
||||
'nsIDOMHTMLOptionElement.label',
|
||||
'nsIDOMHTMLOptionElement.disabled',
|
||||
'nsIDOMHTMLOptionsCollection.item',
|
||||
'nsIDOMHTMLOptionsCollection.length',
|
||||
'nsIDOMHTMLSelectElement.name',
|
||||
'nsIDOMHTMLSelectElement.form',
|
||||
'nsIDOMHTMLSelectElement.add',
|
||||
'nsIDOMHTMLSelectElement.value',
|
||||
'nsIDOMHTMLSelectElement.disabled',
|
||||
'nsIDOMHTMLSelectElement.length',
|
||||
'nsIDOMHTMLSelectElement.remove',
|
||||
'nsIDOMHTMLSelectElement.selectedIndex',
|
||||
'nsIDOMHTMLSelectElement.type',
|
||||
'nsIDOMHTMLSelectElement.options',
|
||||
'nsIDOMHTMLSelectElement.size',
|
||||
'nsIDOMHTMLStyleElement.disabled',
|
||||
'nsIDOMHTMLTableCellElement.colSpan',
|
||||
'nsIDOMHTMLTableCellElement.headers',
|
||||
'nsIDOMHTMLTableCellElement.cellIndex',
|
||||
'nsIDOMHTMLTableCellElement.rowSpan',
|
||||
'nsIDOMHTMLTableCellElement.abbr',
|
||||
'nsIDOMHTMLTableCellElement.scope',
|
||||
'nsIDOMHTMLTableCellElement.noWrap',
|
||||
'nsIDOMHTMLTableCellElement.width',
|
||||
'nsIDOMHTMLTableColElement.span',
|
||||
'nsIDOMHTMLTableColElement.width',
|
||||
'nsIDOMHTMLTableElement.rows',
|
||||
'nsIDOMHTMLTableElement.deleteRow',
|
||||
'nsIDOMHTMLTableElement.summary',
|
||||
'nsIDOMHTMLTableElement.insertRow',
|
||||
'nsIDOMHTMLTableRowElement.sectionRowIndex',
|
||||
'nsIDOMHTMLTableRowElement.rowIndex',
|
||||
'nsIDOMHTMLTableRowElement.cells',
|
||||
'nsIDOMHTMLTableRowElement.deleteCell',
|
||||
'nsIDOMHTMLTableRowElement.insertCell',
|
||||
'nsIDOMHTMLTableSectionElement.rows',
|
||||
'nsIDOMHTMLTableSectionElement.insertRow',
|
||||
'nsIDOMHTMLTableSectionElement.deleteRow',
|
||||
'nsIDOMHTMLTextAreaElement.rows',
|
||||
'nsIDOMHTMLTextAreaElement.name',
|
||||
'nsIDOMHTMLTextAreaElement.form',
|
||||
'nsIDOMHTMLTextAreaElement.defaultValue',
|
||||
'nsIDOMHTMLTextAreaElement.cols',
|
||||
'nsIDOMHTMLTextAreaElement.value',
|
||||
'nsIDOMHTMLTextAreaElement.type',
|
||||
'nsIDOMHTMLTextAreaElement.select',
|
||||
'nsIDOMHTMLTitleElement.text',
|
||||
'nsIDOMHTMLCanvasElement.width',
|
||||
'nsIDOMHTMLCanvasElement.height',
|
||||
'nsIDOMHTMLCanvasElement.getContext',
|
||||
# 'nsIDOMHTMLCanvasElement.toDataURL', # uses GetCurrentNativeCallContext
|
||||
'nsIDOMNSHTMLAnchorElement.text',
|
||||
'nsIDOMNSHTMLDocument.width',
|
||||
'nsIDOMNSHTMLDocument.height',
|
||||
'nsIDOMNSHTMLDocument.domain',
|
||||
'nsIDOMNSHTMLDocument.getSelection',
|
||||
'nsIDOMNSHTMLDocument.designMode',
|
||||
#'nsIDOMNSHTMLDocument.write', # uses GetCurrentNativeCallContext
|
||||
#'nsIDOMNSHTMLDocument.writeln', # uses GetCurrentNativeCallContext
|
||||
'nsIDOMNSHTMLElement.contentEditable',
|
||||
'nsIDOMNSHTMLElement.offsetParent',
|
||||
'nsIDOMNSHTMLElement.innerHTML',
|
||||
'nsIDOMNSHTMLElement.offsetLeft',
|
||||
'nsIDOMNSHTMLElement.offsetTop',
|
||||
'nsIDOMNSHTMLElement.offsetHeight',
|
||||
'nsIDOMNSHTMLElement.offsetWidth',
|
||||
'nsIDOMNSHTMLFrameElement.contentWindow',
|
||||
'nsIDOMNSHTMLImageElement.complete',
|
||||
'nsIDOMNSHTMLInputElement.files',
|
||||
'nsIDOMNSHTMLInputElement.textLength',
|
||||
'nsIDOMNSHTMLInputElement.selectionStart',
|
||||
'nsIDOMNSHTMLInputElement.selectionEnd',
|
||||
'nsIDOMNSHTMLInputElement.setSelectionRange',
|
||||
'nsIDOMNSHTMLOptionCollection.selectedIndex',
|
||||
'nsIDOMNSHTMLOptionElement.text',
|
||||
'nsIDOMNSHTMLSelectElement.item',
|
||||
'nsIDOMNSHTMLTextAreaElement.setSelectionRange',
|
||||
'nsIDOMNSHTMLTextAreaElement.selectionStart',
|
||||
'nsIDOMNSHTMLTextAreaElement.selectionEnd',
|
||||
'nsIDOMNSHTMLTextAreaElement.textLength',
|
||||
|
||||
# dom/public/idl/json - None.
|
||||
# All 4 methods of nsIJSON call GetCurrentNativeCallContext.
|
||||
|
||||
# dom/public/idl/offline - None.
|
||||
|
||||
# dom/public/idl/range
|
||||
'nsIDOMRange.collapsed',
|
||||
|
||||
# dom/public/idl/sidebar - None.
|
||||
|
||||
# dom/public/idl/storage
|
||||
'nsIDOMToString.toString',
|
||||
'nsIDOMStorage.setItem',
|
||||
'nsIDOMStorage.length',
|
||||
'nsIDOMStorage.getItem',
|
||||
'nsIDOMStorage.key',
|
||||
'nsIDOMStorage.removeItem',
|
||||
'nsIDOMStorageItem.value',
|
||||
'nsIDOMStorageWindow.sessionStorage',
|
||||
'nsIDOMStorageWindow.globalStorage',
|
||||
|
||||
# dom/public/idl/stylesheets - None.
|
||||
|
||||
# dom/public/idl/traversal
|
||||
'nsIDOMDocumentTraversal.createNodeIterator',
|
||||
'nsIDOMNodeIterator.nextNode',
|
||||
|
||||
# dom/public/idl/views
|
||||
'nsIDOMDocumentView.defaultView',
|
||||
|
||||
# dom/public/idl/xbl - None.
|
||||
|
||||
# dom/public/idl/xpath
|
||||
'nsIDOMXPathEvaluator.evaluate',
|
||||
'nsIDOMXPathEvaluator.createExpression',
|
||||
'nsIDOMXPathEvaluator.createNSResolver',
|
||||
'nsIDOMXPathExpression.evaluate',
|
||||
'nsIDOMXPathNSResolver.lookupNamespaceURI',
|
||||
'nsIDOMXPathResult.snapshotItem',
|
||||
'nsIDOMXPathResult.iterateNext',
|
||||
'nsIDOMXPathResult.snapshotLength',
|
||||
'nsIDOMXPathResult.resultType',
|
||||
'nsIDOMXPathResult.numberValue',
|
||||
'nsIDOMXPathResult.stringValue',
|
||||
'nsIDOMXPathResult.booleanValue',
|
||||
'nsIDOMXPathResult.singleNodeValue',
|
||||
'nsIDOMNSXPathExpression.evaluateWithContext',
|
||||
|
||||
# dom/public/idl/xul - None.
|
||||
]
|
||||
|
||||
# Most interfaces can be found by searching the includePath; to find
|
||||
# nsIDOMEvent, for example, just look for nsIDOMEvent.idl. But IDL filenames
|
||||
# for very long interface names are slightly abbreviated, and many interfaces
|
||||
# don't have their own files, just for extra wackiness. So qsgen.py needs
|
||||
# a little help.
|
||||
#
|
||||
irregularFilenames = {
|
||||
# abbreviations
|
||||
'nsIDOMNSHTMLOptionCollection': 'nsIDOMNSHTMLOptionCollectn',
|
||||
'nsIDOMHTMLTableSectionElement': 'nsIDOMHTMLTableSectionElem',
|
||||
'nsIDOMHTMLTableCaptionElement': 'nsIDOMHTMLTableCaptionElem',
|
||||
'nsIDOMSVGAnimatedEnumeration': 'nsIDOMSVGAnimatedEnum',
|
||||
'nsIDOMSVGAnimatedPreserveAspectRatio': 'nsIDOMSVGAnimPresAspRatio',
|
||||
'nsIDOMSVGAnimatedTransformList': 'nsIDOMSVGAnimTransformList',
|
||||
'nsIDOMSVGForeignObjectElement': 'nsIDOMSVGForeignObjectElem',
|
||||
'nsIDOMSVGPreserveAspectRatio': 'nsIDOMSVGPresAspectRatio',
|
||||
'nsIDOMSVGTextPositioningElement': 'nsIDOMSVGTextPositionElem',
|
||||
'nsIDOMXULLabeledControlElement': 'nsIDOMXULLabeledControlEl',
|
||||
'nsIDOMXULSelectControlElement': 'nsIDOMXULSelectCntrlEl',
|
||||
'nsIDOMXULSelectControlItemElement': 'nsIDOMXULSelectCntrlItemEl',
|
||||
'nsIDOMXULMultiSelectControlElement': 'nsIDOMXULMultSelectCntrlEl',
|
||||
|
||||
# stowaways
|
||||
'nsIXPointerResult': 'nsIXPointer',
|
||||
'nsIDOMCanvasGradient': 'nsIDOMCanvasRenderingContext2D',
|
||||
'nsIDOMCanvasPattern': 'nsIDOMCanvasRenderingContext2D',
|
||||
'nsIDOMTextMetrics': 'nsIDOMCanvasRenderingContext2D',
|
||||
'nsIGeolocationUpdate': 'nsIGeolocationProvider',
|
||||
'nsIDOMNSCSS2Properties': 'nsIDOMCSS2Properties',
|
||||
'nsIDOMSVGPathSegArcRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegMovetoAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegArcAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegMovetoRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoCubicRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoVerticalAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoQuadraticRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoVerticalRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoHorizontalAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoQuadraticAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoQuadraticSmoothAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoCubicSmoothRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegClosePath': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegLinetoHorizontalRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoCubicSmoothAbs': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoQuadraticSmoothRel': 'nsIDOMSVGPathSeg',
|
||||
'nsIDOMSVGPathSegCurvetoCubicAbs': 'nsIDOMSVGPathSeg',
|
||||
|
||||
# mistakes
|
||||
'nsIDOMXULTextBoxElement': 'nsIDOMXULTextboxElement',
|
||||
'nsIDOMDOMConstructor': 'nsIDOMConstructor'
|
||||
}
|
@ -51,6 +51,7 @@
|
||||
#include "jsobj.h"
|
||||
#include "jsscript.h"
|
||||
#include "nsThreadUtilsInternal.h"
|
||||
#include "dom_quickstubs.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS3(nsXPConnect,
|
||||
nsIXPConnect,
|
||||
@ -2062,8 +2063,8 @@ nsXPConnect::ReleaseJSContext(JSContext * aJSContext, PRBool noGC)
|
||||
if(ccx)
|
||||
{
|
||||
#ifdef DEBUG_xpc_hacker
|
||||
printf("!xpc - deferring destruction of JSContext @ %0x\n",
|
||||
aJSContext);
|
||||
printf("!xpc - deferring destruction of JSContext @ %p\n",
|
||||
(void *)aJSContext);
|
||||
#endif
|
||||
ccx->SetDestroyJSContextInDestructor(JS_TRUE);
|
||||
JS_ClearNewbornRoots(aJSContext);
|
||||
@ -2326,6 +2327,19 @@ nsXPConnect::SetReportAllJSExceptions(PRBool newval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript, notxpcom] PRBool defineDOMQuickStubs (in JSContextPtr cx, in JSObjectPtr proto, in PRUint32 flags, in PRUint32 interfaceCount, [array, size_is (interfaceCount)] in nsIIDPtr interfaceArray); */
|
||||
NS_IMETHODIMP_(PRBool)
|
||||
nsXPConnect::DefineDOMQuickStubs(JSContext * cx,
|
||||
JSObject * proto,
|
||||
PRUint32 flags,
|
||||
PRUint32 interfaceCount,
|
||||
const nsIID * *interfaceArray)
|
||||
{
|
||||
return DOM_DefineQuickStubs(cx, proto, flags,
|
||||
interfaceCount, interfaceArray);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
/* These are here to be callable from a debugger */
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
1026
js/src/xpconnect/src/qsgen.py
Normal file
1026
js/src/xpconnect/src/qsgen.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -147,8 +147,9 @@ XPCConvert::IsMethodReflectable(const XPTMethodDescriptor& info)
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
static JSBool
|
||||
GetISupportsFromJSObject(JSObject* obj, nsISupports** iface)
|
||||
// static
|
||||
JSBool
|
||||
XPCConvert::GetISupportsFromJSObject(JSObject* obj, nsISupports** iface)
|
||||
{
|
||||
JSClass* jsclass = STOBJ_GET_CLASS(obj);
|
||||
NS_ASSERTION(jsclass, "obj has no class");
|
||||
|
@ -2721,6 +2721,7 @@ public:
|
||||
const nsID* iid,
|
||||
nsISupports* aOuter,
|
||||
nsresult* pErr);
|
||||
static JSBool GetISupportsFromJSObject(JSObject* obj, nsISupports** iface);
|
||||
|
||||
/**
|
||||
* Convert a native array into a jsval.
|
||||
@ -2827,13 +2828,14 @@ public:
|
||||
static JSBool SetVerbosity(JSBool state)
|
||||
{JSBool old = sVerbose; sVerbose = state; return old;}
|
||||
|
||||
static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
|
||||
static JSBool CheckForPendingException(nsresult result, JSContext *cx);
|
||||
|
||||
private:
|
||||
static void Verbosify(XPCCallContext& ccx,
|
||||
char** psz, PRBool own);
|
||||
|
||||
static void BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz);
|
||||
static JSBool ThrowExceptionObject(JSContext* cx, nsIException* e);
|
||||
static JSBool CheckForPendingException(nsresult result, XPCCallContext &ccx);
|
||||
|
||||
private:
|
||||
static JSBool sVerbose;
|
||||
@ -3203,6 +3205,9 @@ public:
|
||||
static void ShutDown()
|
||||
{sMainJSThread = nsnull; sMainThreadData = nsnull;}
|
||||
|
||||
static PRBool IsMainThread(JSContext *cx)
|
||||
{ return cx->thread == sMainJSThread; }
|
||||
|
||||
private:
|
||||
XPCPerThreadData();
|
||||
static XPCPerThreadData* GetDataImpl(JSContext *cx);
|
||||
@ -3233,8 +3238,6 @@ private:
|
||||
static XPCPerThreadData* gThreads;
|
||||
static PRUintn gTLSIndex;
|
||||
|
||||
friend class AutoJSSuspendNonMainThreadRequest;
|
||||
|
||||
// Cached value of cx->thread on the main thread.
|
||||
static void *sMainJSThread;
|
||||
|
||||
@ -3573,7 +3576,7 @@ public:
|
||||
|
||||
private:
|
||||
void SuspendRequest() {
|
||||
if (mCX && mCX->thread != XPCPerThreadData::sMainJSThread)
|
||||
if (mCX && XPCPerThreadData::IsMainThread(mCX))
|
||||
mDepth = JS_SuspendRequest(mCX);
|
||||
else
|
||||
mCX = nsnull;
|
||||
|
799
js/src/xpconnect/src/xpcquickstubs.cpp
Normal file
799
js/src/xpconnect/src/xpcquickstubs.cpp
Normal file
@ -0,0 +1,799 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Orendorff <jorendorff@mozilla.com>
|
||||
*
|
||||
* 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 "jsapi.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsstr.h"
|
||||
#include "jscntxt.h" /* for error messages */
|
||||
#include "nsCOMPtr.h"
|
||||
#include "xpcprivate.h"
|
||||
#include "xpcinlines.h"
|
||||
#include "xpcquickstubs.h"
|
||||
#include "XPCWrapper.h"
|
||||
#include "XPCNativeWrapper.h"
|
||||
|
||||
static const xpc_qsHashEntry *
|
||||
LookupEntry(PRUint32 tableSize, const xpc_qsHashEntry *table, const nsID &iid)
|
||||
{
|
||||
size_t i;
|
||||
const xpc_qsHashEntry *p;
|
||||
|
||||
i = iid.m0 % tableSize;
|
||||
do
|
||||
{
|
||||
p = table + i;
|
||||
if(p->iid.Equals(iid))
|
||||
return p;
|
||||
i = p->chain;
|
||||
} while(i != XPC_QS_NULL_INDEX);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
static const xpc_qsHashEntry *
|
||||
LookupInterfaceOrAncestor(PRUint32 tableSize, const xpc_qsHashEntry *table,
|
||||
const nsID &iid)
|
||||
{
|
||||
const xpc_qsHashEntry *p = LookupEntry(tableSize, table, iid);
|
||||
if(!p)
|
||||
{
|
||||
/*
|
||||
* On a miss, we have to search for every interface the object
|
||||
* supports, including ancestors.
|
||||
*/
|
||||
nsCOMPtr<nsIInterfaceInfo> info;
|
||||
if(NS_FAILED(nsXPConnect::GetXPConnect()->GetInfoForIID(
|
||||
&iid, getter_AddRefs(info))))
|
||||
return nsnull;
|
||||
|
||||
nsIID *piid;
|
||||
for(;;)
|
||||
{
|
||||
nsCOMPtr<nsIInterfaceInfo> parent;
|
||||
if(NS_FAILED(info->GetParent(getter_AddRefs(parent))) ||
|
||||
!parent ||
|
||||
NS_FAILED(parent->GetInterfaceIID(&piid)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
p = LookupEntry(tableSize, table, *piid);
|
||||
if(p)
|
||||
break;
|
||||
info.swap(parent);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, uintN flags,
|
||||
PRUint32 ifacec, const nsIID **interfaces,
|
||||
PRUint32 tableSize, const xpc_qsHashEntry *table)
|
||||
{
|
||||
for(uint32 i = 0; i < ifacec; i++)
|
||||
{
|
||||
const nsID &iid = *interfaces[i];
|
||||
const xpc_qsHashEntry *entry =
|
||||
LookupInterfaceOrAncestor(tableSize, table, iid);
|
||||
|
||||
if(entry)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
// Define quick stubs for attributes.
|
||||
const xpc_qsPropertySpec *ps = entry->properties;
|
||||
if(ps)
|
||||
{
|
||||
for(; ps->name; ps++)
|
||||
{
|
||||
if(!JS_DefineProperty(cx, proto, ps->name, JSVAL_VOID,
|
||||
ps->getter, ps->setter,
|
||||
flags | JSPROP_SHARED))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Define quick stubs for methods.
|
||||
const xpc_qsFunctionSpec *fs = entry->functions;
|
||||
if(fs)
|
||||
{
|
||||
for(; fs->name; fs++)
|
||||
{
|
||||
if(!JS_DefineFunction(
|
||||
cx, proto, fs->name,
|
||||
reinterpret_cast<JSNative>(fs->native),
|
||||
fs->arity, flags | JSFUN_FAST_NATIVE))
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Next.
|
||||
size_t j = entry->parentInterface;
|
||||
if(j == XPC_QS_NULL_INDEX)
|
||||
break;
|
||||
entry = table + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsThrow(JSContext *cx, nsresult rv)
|
||||
{
|
||||
XPCThrower::Throw(rv, cx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface name and member name (for error messages).
|
||||
*
|
||||
* We could instead have each quick stub pass its name to the error-handling
|
||||
* functions, as that name is statically known. But that would be redundant;
|
||||
* the information is handy at runtime anyway. Also, this code often produces
|
||||
* a more specific error message, e.g. "[nsIDOMHTMLDocument.appendChild]"
|
||||
* rather than "[nsIDOMNode.appendChild]".
|
||||
*/
|
||||
static void
|
||||
GetMemberInfo(XPCWrappedNative *wrapper,
|
||||
jsval memberId,
|
||||
const char **ifaceName,
|
||||
const char **memberName)
|
||||
{
|
||||
// Get the interface name. From DefinePropertyIfFound (in
|
||||
// xpcwrappednativejsops.cpp) and XPCThrower::Verbosify.
|
||||
//
|
||||
// We could instead make the quick stub could pass in its interface name,
|
||||
// but this code often produces a more specific error message, e.g.
|
||||
*ifaceName = "Unknown";
|
||||
XPCWrappedNativeProto *proto = wrapper->GetProto();
|
||||
if(proto)
|
||||
{
|
||||
XPCNativeSet *set = proto->GetSet();
|
||||
if(set)
|
||||
{
|
||||
XPCNativeMember *member;
|
||||
XPCNativeInterface *iface;
|
||||
|
||||
if(set->FindMember(memberId, &member, &iface))
|
||||
*ifaceName = iface->GetNameString();
|
||||
}
|
||||
}
|
||||
|
||||
*memberName = (JSVAL_IS_STRING(memberId)
|
||||
? JS_GetStringBytes(JSVAL_TO_STRING(memberId))
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
static void
|
||||
GetMethodInfo(JSContext *cx,
|
||||
XPCWrappedNative *wrapper,
|
||||
jsval *vp,
|
||||
const char **ifaceName,
|
||||
const char **memberName)
|
||||
{
|
||||
JSObject *funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));
|
||||
NS_ASSERTION(JS_ObjectIsFunction(cx, funobj),
|
||||
"JSFastNative callee should be Function object");
|
||||
JSString *str = JS_GetFunctionId((JSFunction *) JS_GetPrivate(cx, funobj));
|
||||
jsval methodId = str ? STRING_TO_JSVAL(str) : JSVAL_NULL;
|
||||
|
||||
GetMemberInfo(wrapper, methodId, ifaceName, memberName);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ThrowCallFailed(JSContext *cx, nsresult rv,
|
||||
const char *ifaceName, const char *memberName)
|
||||
{
|
||||
// From XPCThrower::ThrowBadResult.
|
||||
char* sz;
|
||||
const char* format;
|
||||
const char* name;
|
||||
|
||||
/*
|
||||
* If there is a pending exception when the native call returns and
|
||||
* it has the same error result as returned by the native call, then
|
||||
* the native call may be passing through an error from a previous JS
|
||||
* call. So we'll just throw that exception into our JS.
|
||||
*/
|
||||
if(XPCThrower::CheckForPendingException(rv, cx))
|
||||
return JS_FALSE;
|
||||
|
||||
// else...
|
||||
|
||||
if(!nsXPCException::NameAndFormatForNSResult(
|
||||
NS_ERROR_XPC_NATIVE_RETURNED_FAILURE, nsnull, &format) ||
|
||||
!format)
|
||||
{
|
||||
format = "";
|
||||
}
|
||||
|
||||
if(nsXPCException::NameAndFormatForNSResult(rv, &name, nsnull)
|
||||
&& name)
|
||||
{
|
||||
sz = JS_smprintf("%s 0x%x (%s) [%s.%s]",
|
||||
format, rv, name, ifaceName, memberName);
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = JS_smprintf("%s 0x%x [%s.%s]",
|
||||
format, rv, ifaceName, memberName);
|
||||
}
|
||||
|
||||
XPCThrower::BuildAndThrowException(cx, rv, sz);
|
||||
|
||||
if(sz)
|
||||
JS_smprintf_free(sz);
|
||||
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval memberId)
|
||||
{
|
||||
const char *ifaceName, *memberName;
|
||||
GetMemberInfo(wrapper, memberId, &ifaceName, &memberName);
|
||||
return ThrowCallFailed(cx, rv, ifaceName, memberName);
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsThrowMethodFailed(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval *vp)
|
||||
{
|
||||
const char *ifaceName, *memberName;
|
||||
GetMethodInfo(cx, wrapper, vp, &ifaceName, &memberName);
|
||||
return ThrowCallFailed(cx, rv, ifaceName, memberName);
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsThrowMethodFailedWithCcx(XPCCallContext &ccx, nsresult rv)
|
||||
{
|
||||
ThrowBadResult(rv, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ThrowBadArg(JSContext *cx, nsresult rv,
|
||||
const char *ifaceName, const char *memberName, uintN paramnum)
|
||||
{
|
||||
// From XPCThrower::ThrowBadParam.
|
||||
char* sz;
|
||||
const char* format;
|
||||
|
||||
if(!nsXPCException::NameAndFormatForNSResult(rv, nsnull, &format))
|
||||
format = "";
|
||||
|
||||
sz = JS_smprintf("%s arg %u [%s.%s]",
|
||||
format, (unsigned int) paramnum, ifaceName, memberName);
|
||||
|
||||
XPCThrower::BuildAndThrowException(cx, rv, sz);
|
||||
|
||||
if(sz)
|
||||
JS_smprintf_free(sz);
|
||||
}
|
||||
|
||||
void
|
||||
xpc_qsThrowBadArg(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval *vp, uintN paramnum)
|
||||
{
|
||||
const char *ifaceName, *memberName;
|
||||
GetMethodInfo(cx, wrapper, vp, &ifaceName, &memberName);
|
||||
ThrowBadArg(cx, rv, ifaceName, memberName, paramnum);
|
||||
}
|
||||
|
||||
void
|
||||
xpc_qsThrowBadArgWithCcx(XPCCallContext &ccx, nsresult rv, uintN paramnum)
|
||||
{
|
||||
XPCThrower::ThrowBadParam(rv, paramnum, ccx);
|
||||
}
|
||||
|
||||
void
|
||||
xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval propId)
|
||||
{
|
||||
const char *ifaceName, *memberName;
|
||||
GetMemberInfo(wrapper, propId, &ifaceName, &memberName);
|
||||
ThrowBadArg(cx, rv, ifaceName, memberName, 0);
|
||||
}
|
||||
|
||||
xpc_qsDOMString::xpc_qsDOMString(JSContext *cx, jsval *pval)
|
||||
{
|
||||
// From the T_DOMSTRING case in XPCConvert::JSData2Native.
|
||||
typedef implementation_type::char_traits traits;
|
||||
jsval v;
|
||||
JSString *s;
|
||||
const jschar *chars;
|
||||
size_t len;
|
||||
|
||||
v = *pval;
|
||||
if(JSVAL_IS_STRING(v))
|
||||
{
|
||||
s = JSVAL_TO_STRING(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(JSVAL_IS_NULL(v))
|
||||
{
|
||||
(new(mBuf) implementation_type(
|
||||
traits::sEmptyBuffer, PRUint32(0)))->SetIsVoid(PR_TRUE);
|
||||
mValid = JS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
s = JS_ValueToString(cx, v);
|
||||
if(!s)
|
||||
{
|
||||
mValid = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
*pval = STRING_TO_JSVAL(s); // Root the new string.
|
||||
}
|
||||
|
||||
len = JS_GetStringLength(s);
|
||||
chars = (len == 0 ? traits::sEmptyBuffer : JS_GetStringChars(s));
|
||||
new(mBuf) implementation_type(chars, len);
|
||||
mValid = JS_TRUE;
|
||||
}
|
||||
|
||||
xpc_qsAString::xpc_qsAString(JSContext *cx, jsval *pval)
|
||||
{
|
||||
// From the T_ASTRING case in XPCConvert::JSData2Native.
|
||||
typedef implementation_type::char_traits traits;
|
||||
jsval v;
|
||||
JSString *s;
|
||||
const jschar *chars;
|
||||
size_t len;
|
||||
|
||||
v = *pval;
|
||||
if(JSVAL_IS_STRING(v))
|
||||
{
|
||||
s = JSVAL_TO_STRING(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
|
||||
{
|
||||
(new(mBuf) implementation_type(
|
||||
traits::sEmptyBuffer, PRUint32(0)))->SetIsVoid(PR_TRUE);
|
||||
mValid = JS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
s = JS_ValueToString(cx, v);
|
||||
if(!s)
|
||||
{
|
||||
mValid = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
*pval = STRING_TO_JSVAL(s); // Root the new string.
|
||||
}
|
||||
|
||||
len = JS_GetStringLength(s);
|
||||
chars = (len == 0 ? traits::sEmptyBuffer : JS_GetStringChars(s));
|
||||
new(mBuf) implementation_type(chars, len);
|
||||
mValid = JS_TRUE;
|
||||
}
|
||||
|
||||
xpc_qsACString::xpc_qsACString(JSContext *cx, jsval *pval)
|
||||
{
|
||||
// From the T_CSTRING case in XPCConvert::JSData2Native.
|
||||
jsval v;
|
||||
JSString *s;
|
||||
|
||||
v = *pval;
|
||||
if(JSVAL_IS_STRING(v))
|
||||
{
|
||||
s = JSVAL_TO_STRING(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
|
||||
{
|
||||
(new(mBuf) implementation_type())->SetIsVoid(PR_TRUE);
|
||||
mValid = JS_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
s = JS_ValueToString(cx, v);
|
||||
if(!s)
|
||||
{
|
||||
mValid = JS_FALSE;
|
||||
return;
|
||||
}
|
||||
*pval = STRING_TO_JSVAL(s); // Root the new string.
|
||||
}
|
||||
|
||||
const char *bytes = JS_GetStringBytes(s);
|
||||
size_t len = JS_GetStringLength(s);
|
||||
new(mBuf) implementation_type(bytes, len);
|
||||
mValid = JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsUnwrapThisImpl(JSContext *cx,
|
||||
JSObject *obj,
|
||||
const nsIID &iid,
|
||||
void **ppThis,
|
||||
XPCWrappedNative **ppWrapper)
|
||||
{
|
||||
// From XPCWrappedNative::GetWrappedNativeOfJSObject.
|
||||
//
|
||||
// Usually IS_WRAPPER_CLASS is true the first time through the while loop,
|
||||
// and the QueryInterface then succeeds.
|
||||
|
||||
NS_ASSERTION(obj, "this == null");
|
||||
|
||||
JSObject *cur = obj;
|
||||
while(cur)
|
||||
{
|
||||
JSClass *clazz;
|
||||
XPCWrappedNative *wrapper;
|
||||
nsISupports *idobj;
|
||||
nsresult rv;
|
||||
|
||||
clazz = STOBJ_GET_CLASS(cur);
|
||||
if(IS_WRAPPER_CLASS(clazz))
|
||||
{
|
||||
wrapper = (XPCWrappedNative*) xpc_GetJSPrivate(cur);
|
||||
NS_ASSERTION(wrapper, "XPCWN wrapping nothing");
|
||||
}
|
||||
else if(clazz == &XPC_WN_Tearoff_JSClass)
|
||||
{
|
||||
wrapper = (XPCWrappedNative*) xpc_GetJSPrivate(STOBJ_GET_PARENT(cur));
|
||||
NS_ASSERTION(wrapper, "XPCWN wrapping nothing");
|
||||
}
|
||||
else if(clazz == &sXPC_XOW_JSClass.base)
|
||||
{
|
||||
JSObject *unsafeObj = XPCWrapper::Unwrap(cx, cur);
|
||||
if(unsafeObj)
|
||||
{
|
||||
cur = unsafeObj;
|
||||
continue;
|
||||
}
|
||||
|
||||
// This goto is a bug, dutifully copied from
|
||||
// XPCWrappedNative::GetWrappedNativeOfJSObject.
|
||||
goto next;
|
||||
}
|
||||
else if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
{
|
||||
wrapper = XPCNativeWrapper::GetWrappedNative(cur);
|
||||
NS_ASSERTION(wrapper, "XPCNativeWrapper wrapping nothing");
|
||||
}
|
||||
else if(IsXPCSafeJSObjectWrapperClass(clazz))
|
||||
{
|
||||
cur = STOBJ_GET_PARENT(cur);
|
||||
NS_ASSERTION(cur, "SJOW wrapping nothing");
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
goto next;
|
||||
}
|
||||
|
||||
idobj = wrapper->GetIdentityObject();
|
||||
rv = idobj->QueryInterface(iid, ppThis);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
*ppWrapper = wrapper;
|
||||
return JS_TRUE;
|
||||
}
|
||||
if(rv != NS_ERROR_NO_INTERFACE)
|
||||
return xpc_qsThrow(cx, rv);
|
||||
|
||||
next:
|
||||
cur = STOBJ_GET_PROTO(cur);
|
||||
}
|
||||
|
||||
// If we didn't find a wrapper using the given obj, try again with obj's
|
||||
// outer object, if it's got one.
|
||||
|
||||
JSClass *clazz = STOBJ_GET_CLASS(obj);
|
||||
|
||||
if((clazz->flags & JSCLASS_IS_EXTENDED) &&
|
||||
((JSExtendedClass*)clazz)->outerObject)
|
||||
{
|
||||
JSObject *outer = ((JSExtendedClass*)clazz)->outerObject(cx, obj);
|
||||
|
||||
// Protect against infinite recursion through XOWs.
|
||||
JSObject *unsafeObj;
|
||||
clazz = STOBJ_GET_CLASS(outer);
|
||||
if(clazz == &sXPC_XOW_JSClass.base &&
|
||||
(unsafeObj = XPCWrapper::Unwrap(cx, outer)))
|
||||
{
|
||||
outer = unsafeObj;
|
||||
}
|
||||
|
||||
if(outer && outer != obj)
|
||||
return xpc_qsUnwrapThisImpl(cx, outer, iid, ppThis, ppWrapper);
|
||||
}
|
||||
|
||||
return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_OP_ON_WN_PROTO);
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsUnwrapThisFromCcxImpl(XPCCallContext &ccx,
|
||||
const nsIID &iid,
|
||||
void **ppThis)
|
||||
{
|
||||
XPCWrappedNative *wrapper = ccx.GetWrapper();
|
||||
if(!wrapper)
|
||||
return xpc_qsThrow(ccx.GetJSContext(), NS_ERROR_XPC_BAD_OP_ON_WN_PROTO);
|
||||
if(!wrapper->IsValid())
|
||||
return xpc_qsThrow(ccx.GetJSContext(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
|
||||
|
||||
nsISupports *idobj = wrapper->GetIdentityObject();
|
||||
nsresult rv = idobj->QueryInterface(iid, ppThis);
|
||||
if(NS_FAILED(rv))
|
||||
return xpc_qsThrow(ccx.GetJSContext(), rv);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpc_qsUnwrapArgImpl(JSContext *cx,
|
||||
jsval v,
|
||||
const nsIID &iid,
|
||||
void **ppArg)
|
||||
{
|
||||
// From XPCConvert::JSData2Native
|
||||
if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
|
||||
return NS_OK;
|
||||
|
||||
if(!JSVAL_IS_OBJECT(v))
|
||||
{
|
||||
return ((JSVAL_IS_INT(v) && JSVAL_TO_INT(v) == 0)
|
||||
? NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL
|
||||
: NS_ERROR_XPC_BAD_CONVERT_JS);
|
||||
}
|
||||
JSObject *src = JSVAL_TO_OBJECT(v);
|
||||
|
||||
// From XPCConvert::JSObject2NativeInterface
|
||||
XPCWrappedNative* wrappedNative =
|
||||
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, src);
|
||||
nsISupports *iface;
|
||||
if(wrappedNative)
|
||||
{
|
||||
iface = wrappedNative->GetIdentityObject();
|
||||
if(NS_FAILED(iface->QueryInterface(iid, ppArg)))
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
return NS_OK;
|
||||
}
|
||||
// else...
|
||||
// Slow path.
|
||||
|
||||
// XXX E4X breaks the world. Don't try wrapping E4X objects!
|
||||
// This hack can be removed (or changed accordingly) when the
|
||||
// DOM <-> E4X bindings are complete, see bug 270553
|
||||
if(JS_TypeOfValue(cx, OBJECT_TO_JSVAL(src)) == JSTYPE_XML)
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
|
||||
// Does the JSObject have 'nsISupportness'?
|
||||
// XXX hmm, I wonder if this matters anymore with no
|
||||
// oldstyle DOM objects around.
|
||||
if(XPCConvert::GetISupportsFromJSObject(src, &iface))
|
||||
{
|
||||
if(!iface || NS_FAILED(iface->QueryInterface(iid, ppArg)))
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Create the ccx needed for quick stubs.
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if(!ccx.IsValid())
|
||||
return NS_ERROR_XPC_BAD_CONVERT_JS;
|
||||
|
||||
nsXPCWrappedJS *wrapper;
|
||||
nsresult rv =
|
||||
nsXPCWrappedJS::GetNewOrUsed(ccx, src, iid, nsnull, &wrapper);
|
||||
if(NS_FAILED(rv) || !wrapper)
|
||||
return rv;
|
||||
|
||||
// We need to go through the QueryInterface logic to make this return
|
||||
// the right thing for the various 'special' interfaces; e.g.
|
||||
// nsIPropertyBag. We must use AggregatedQueryInterface in cases where
|
||||
// there is an outer to avoid nasty recursion.
|
||||
rv = wrapper->QueryInterface(iid, ppArg);
|
||||
NS_RELEASE(wrapper);
|
||||
return rv;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsJsvalToCharStr(JSContext *cx, jsval *pval, char **pstr)
|
||||
{
|
||||
jsval v = *pval;
|
||||
JSString *str;
|
||||
|
||||
if(JSVAL_IS_STRING(v))
|
||||
{
|
||||
str = JSVAL_TO_STRING(v);
|
||||
}
|
||||
else if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
|
||||
{
|
||||
*pstr = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(str = JS_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
*pval = STRING_TO_JSVAL(str); // Root the new string.
|
||||
}
|
||||
|
||||
*pstr = JS_GetStringBytes(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsJsvalToWcharStr(JSContext *cx, jsval *pval, PRUnichar **pstr)
|
||||
{
|
||||
jsval v = *pval;
|
||||
JSString *str;
|
||||
|
||||
if(JSVAL_IS_STRING(v))
|
||||
{
|
||||
str = JSVAL_TO_STRING(v);
|
||||
}
|
||||
else if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v))
|
||||
{
|
||||
*pstr = NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!(str = JS_ValueToString(cx, v)))
|
||||
return JS_FALSE;
|
||||
*pval = STRING_TO_JSVAL(str); // Root the new string.
|
||||
}
|
||||
|
||||
*pstr = JS_GetStringChars(str);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsStringToJsval(JSContext *cx, const nsAString &str, jsval *rval)
|
||||
{
|
||||
// From the T_DOMSTRING case in XPCConvert::NativeData2JS.
|
||||
if(str.IsVoid())
|
||||
{
|
||||
*rval = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSString *jsstr = XPCStringConvert::ReadableToJSString(cx, str);
|
||||
if(!jsstr)
|
||||
return JS_FALSE;
|
||||
*rval = STRING_TO_JSVAL(jsstr);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx, nsISupports *p,
|
||||
const nsIID &iid, jsval *rval)
|
||||
{
|
||||
// From the T_INTERFACE case in XPCConvert::NativeData2JS.
|
||||
// This is one of the slowest things quick stubs do.
|
||||
|
||||
JSObject *scope = ccx.GetCurrentJSObject();
|
||||
NS_ASSERTION(scope, "bad ccx");
|
||||
|
||||
// XXX The OBJ_IS_NOT_GLOBAL here is not really right. In
|
||||
// fact, this code is depending on the fact that the
|
||||
// global object will not have been collected, and
|
||||
// therefore this NativeInterface2JSObject will not end up
|
||||
// creating a new XPCNativeScriptableShared.
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
|
||||
nsresult rv;
|
||||
if(!XPCConvert::NativeInterface2JSObject(ccx, getter_AddRefs(holder),
|
||||
p, &iid, scope, PR_TRUE,
|
||||
OBJ_IS_NOT_GLOBAL, &rv))
|
||||
{
|
||||
// I can't tell if NativeInterface2JSObject throws JS exceptions
|
||||
// or not. This is a sloppy stab at the right semantics; the
|
||||
// method really ought to be fixed to behave consistently.
|
||||
if(!JS_IsExceptionPending(ccx))
|
||||
xpc_qsThrow(ccx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if(holder)
|
||||
{
|
||||
JSObject* jsobj;
|
||||
if(NS_FAILED(holder->GetJSObject(&jsobj)))
|
||||
return JS_FALSE;
|
||||
#ifdef DEBUG
|
||||
if(!STOBJ_GET_PARENT(jsobj))
|
||||
NS_ASSERTION(STOBJ_GET_CLASS(jsobj)->flags & JSCLASS_IS_GLOBAL,
|
||||
"Why did we recreate this wrapper?");
|
||||
#endif
|
||||
*rval = OBJECT_TO_JSVAL(jsobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
*rval = JSVAL_NULL;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsVariantToJsval(XPCCallContext &ccx,
|
||||
nsIVariant *p,
|
||||
uintN paramNum,
|
||||
jsval *rval)
|
||||
{
|
||||
// From the T_INTERFACE case in XPCConvert::NativeData2JS.
|
||||
// Error handling is in XPCWrappedNative::CallMethod.
|
||||
if(p)
|
||||
{
|
||||
nsresult rv;
|
||||
JSBool ok = XPCVariant::VariantDataToJS(ccx, p,
|
||||
ccx.GetCurrentJSObject(),
|
||||
&rv, rval);
|
||||
if (!ok)
|
||||
XPCThrower::ThrowBadParam(rv, 0, ccx);
|
||||
return ok;
|
||||
}
|
||||
*rval = JSVAL_NULL;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsReadOnlySetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_GETTER_ONLY, NULL);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
xpc_qsAssertContextOK(JSContext *cx)
|
||||
{
|
||||
XPCPerThreadData *thread = XPCPerThreadData::GetData(cx);
|
||||
XPCJSContextStack* stack = thread->GetJSContextStack();
|
||||
|
||||
JSContext* topJSContext = nsnull;
|
||||
nsresult rv = stack->Peek(&topJSContext);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "XPCJSContextStack::Peek failed");
|
||||
|
||||
// This is what we're actually trying to assert here.
|
||||
NS_ASSERTION(cx == topJSContext, "wrong context on XPCJSContextStack!");
|
||||
|
||||
NS_ASSERTION(XPCPerThreadData::IsMainThread(cx),
|
||||
"XPConnect quick stub called on non-main thread");
|
||||
}
|
||||
#endif
|
368
js/src/xpconnect/src/xpcquickstubs.h
Normal file
368
js/src/xpconnect/src/xpcquickstubs.h
Normal file
@ -0,0 +1,368 @@
|
||||
/* -*- Mode: C; tab-width: 8; 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 code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jason Orendorff <jorendorff@mozilla.com>
|
||||
*
|
||||
* 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 xpcquickstubs_h___
|
||||
#define xpcquickstubs_h___
|
||||
|
||||
/* xpcquickstubs.h - Support functions used only by quick stubs. */
|
||||
|
||||
class XPCCallContext;
|
||||
|
||||
#define XPC_QS_NULL_INDEX ((size_t) -1)
|
||||
|
||||
struct xpc_qsPropertySpec {
|
||||
const char *name;
|
||||
JSPropertyOp getter;
|
||||
JSPropertyOp setter;
|
||||
};
|
||||
|
||||
struct xpc_qsFunctionSpec {
|
||||
const char *name;
|
||||
JSFastNative native;
|
||||
uintN arity;
|
||||
};
|
||||
|
||||
/** A table mapping interfaces to quick stubs. */
|
||||
struct xpc_qsHashEntry {
|
||||
nsID iid;
|
||||
const xpc_qsPropertySpec *properties;
|
||||
const xpc_qsFunctionSpec *functions;
|
||||
// These last two fields index to other entries in the same table.
|
||||
// XPC_QS_NULL_ENTRY indicates there are no more entries in the chain.
|
||||
size_t parentInterface;
|
||||
size_t chain;
|
||||
};
|
||||
|
||||
JSBool
|
||||
xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, uintN extraFlags,
|
||||
PRUint32 ifacec, const nsIID **interfaces,
|
||||
PRUint32 tableSize, const xpc_qsHashEntry *table);
|
||||
|
||||
/** Raise an exception on @a cx and return JS_FALSE. */
|
||||
JSBool
|
||||
xpc_qsThrow(JSContext *cx, nsresult rv);
|
||||
|
||||
/** Elaborately fail after an XPCOM method returned rv. */
|
||||
JSBool
|
||||
xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval memberId);
|
||||
|
||||
JSBool
|
||||
xpc_qsThrowMethodFailed(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval *vp);
|
||||
|
||||
JSBool
|
||||
xpc_qsThrowMethodFailedWithCcx(XPCCallContext &ccx, nsresult rv);
|
||||
|
||||
/** Elaborately fail after converting an argument fails. */
|
||||
void
|
||||
xpc_qsThrowBadArg(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval *vp, uintN paramnum);
|
||||
|
||||
void
|
||||
xpc_qsThrowBadArgWithCcx(XPCCallContext &ccx, nsresult rv, uintN paramnum);
|
||||
|
||||
void
|
||||
xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
|
||||
XPCWrappedNative *wrapper, jsval propId);
|
||||
|
||||
|
||||
/* Functions for converting values between COM and JS. */
|
||||
|
||||
inline JSBool
|
||||
xpc_qsInt32ToJsval(JSContext *cx, PRInt32 i, jsval *rv)
|
||||
{
|
||||
if(INT_FITS_IN_JSVAL(i))
|
||||
{
|
||||
*rv = INT_TO_JSVAL(i);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_NewDoubleValue(cx, i, rv);
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
xpc_qsUint32ToJsval(JSContext *cx, PRUint32 u, jsval *rv)
|
||||
{
|
||||
if(u <= JSVAL_INT_MAX)
|
||||
{
|
||||
*rv = INT_TO_JSVAL(u);
|
||||
return JS_TRUE;
|
||||
}
|
||||
return JS_NewDoubleValue(cx, u, rv);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
|
||||
#define INT64_TO_DOUBLE(i) ((jsdouble) (i))
|
||||
// Win32 can't handle uint64 to double conversion
|
||||
#define UINT64_TO_DOUBLE(u) ((jsdouble) (int64) (u))
|
||||
|
||||
#else
|
||||
|
||||
inline jsdouble
|
||||
INT64_TO_DOUBLE(const int64 &v)
|
||||
{
|
||||
jsdouble d;
|
||||
LL_L2D(d, v);
|
||||
return d;
|
||||
}
|
||||
|
||||
// if !HAVE_LONG_LONG, then uint64 is a typedef of int64
|
||||
#define UINT64_TO_DOUBLE INT64_TO_DOUBLE
|
||||
|
||||
#endif
|
||||
|
||||
inline JSBool
|
||||
xpc_qsInt64ToJsval(JSContext *cx, PRInt64 i, jsval *rv)
|
||||
{
|
||||
double d = INT64_TO_DOUBLE(i);
|
||||
return JS_NewNumberValue(cx, d, rv);
|
||||
}
|
||||
|
||||
inline JSBool
|
||||
xpc_qsUint64ToJsval(JSContext *cx, PRUint64 u, jsval *rv)
|
||||
{
|
||||
double d = UINT64_TO_DOUBLE(u);
|
||||
return JS_NewNumberValue(cx, d, rv);
|
||||
}
|
||||
|
||||
|
||||
/* Classes for converting jsvals to string types. */
|
||||
|
||||
template <class S, class T>
|
||||
class xpc_qsBasicString
|
||||
{
|
||||
public:
|
||||
typedef S interface_type;
|
||||
typedef T implementation_type;
|
||||
|
||||
~xpc_qsBasicString()
|
||||
{
|
||||
if (mValid)
|
||||
Ptr()->~implementation_type();
|
||||
}
|
||||
|
||||
JSBool IsValid() { return mValid; }
|
||||
|
||||
implementation_type *Ptr()
|
||||
{
|
||||
return reinterpret_cast<implementation_type *>(mBuf);
|
||||
}
|
||||
|
||||
operator interface_type &()
|
||||
{
|
||||
return *Ptr();
|
||||
}
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Neither field is initialized; that is left to the derived class
|
||||
* constructor. However, the destructor destroys the string object
|
||||
* stored in mBuf, if mValid is true.
|
||||
*/
|
||||
void *mBuf[JS_HOWMANY(sizeof(implementation_type), sizeof(void *))];
|
||||
JSBool mValid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class for converting a jsval to DOMString.
|
||||
*
|
||||
* xpc_qsDOMString arg0(cx, &argv[0]);
|
||||
* if (!arg0.IsValid())
|
||||
* return JS_FALSE;
|
||||
*
|
||||
* The second argument to the constructor is an in-out parameter. It must
|
||||
* point to a rooted jsval, such as a JSNative argument or return value slot.
|
||||
* The value in the jsval on entry is converted to a string. The constructor
|
||||
* may overwrite that jsval with a string value, to protect the characters of
|
||||
* the string from garbage collection. The caller must leave the jsval alone
|
||||
* for the lifetime of the xpc_qsDOMString.
|
||||
*/
|
||||
class xpc_qsDOMString : public xpc_qsBasicString<nsAString, nsDependentString>
|
||||
{
|
||||
public:
|
||||
xpc_qsDOMString(JSContext *cx, jsval *pval);
|
||||
};
|
||||
|
||||
/**
|
||||
* The same as xpc_qsDOMString, but with slightly different conversion behavior,
|
||||
* corresponding to the [astring] magic XPIDL annotation rather than [domstring].
|
||||
*/
|
||||
class xpc_qsAString : public xpc_qsBasicString<nsAString, nsDependentString>
|
||||
{
|
||||
public:
|
||||
xpc_qsAString(JSContext *cx, jsval *pval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Like xpc_qsDOMString and xpc_qsAString, but for XPIDL native types annotated
|
||||
* with [cstring] rather than [domstring] or [astring].
|
||||
*/
|
||||
class xpc_qsACString : public xpc_qsBasicString<nsACString, nsCString>
|
||||
{
|
||||
public:
|
||||
xpc_qsACString(JSContext *cx, jsval *pval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a jsval to char*, returning JS_TRUE on success.
|
||||
*
|
||||
* @param cx
|
||||
* A context.
|
||||
* @param pval
|
||||
* In/out. *pval is the jsval to convert; the function may write to *pval,
|
||||
* using it as a GC root (like xpc_qsDOMString's constructor).
|
||||
* @param pstr
|
||||
* Out. On success *pstr receives the converted string or NULL if *pval is
|
||||
* null or undefined. Unicode data is garbled as with JS_GetStringBytes.
|
||||
*/
|
||||
JSBool
|
||||
xpc_qsJsvalToCharStr(JSContext *cx, jsval *pval, char **pstr);
|
||||
|
||||
JSBool
|
||||
xpc_qsJsvalToWcharStr(JSContext *cx, jsval *pval, PRUnichar **pstr);
|
||||
|
||||
|
||||
/** Convert an nsAString to jsval, returning JS_TRUE on success. */
|
||||
JSBool
|
||||
xpc_qsStringToJsval(JSContext *cx, const nsAString &str, jsval *rval);
|
||||
|
||||
JSBool
|
||||
xpc_qsUnwrapThisImpl(JSContext *cx,
|
||||
JSObject *obj,
|
||||
const nsIID &iid,
|
||||
void **ppThis,
|
||||
XPCWrappedNative **ppWrapper);
|
||||
|
||||
/**
|
||||
* Search @a obj and its prototype chain for an XPCOM object that implements
|
||||
* the interface T.
|
||||
*
|
||||
* If an object implementing T is found, AddRef it, store the pointer in
|
||||
* @a *ppThis, store a pointer to the wrapper in @a *ppWrapper, and return
|
||||
* JS_TRUE. Otherwise, raise an exception on @a cx and return JS_FALSE.
|
||||
*
|
||||
* This does not consult inner objects. It does support XPConnect tear-offs
|
||||
* and it sees through XOWs, XPCNativeWrappers, and SafeJSObjectWrappers.
|
||||
*
|
||||
* Requires a request on @a cx.
|
||||
*/
|
||||
template <class T>
|
||||
inline JSBool
|
||||
xpc_qsUnwrapThis(JSContext *cx,
|
||||
JSObject *obj,
|
||||
T **ppThis,
|
||||
XPCWrappedNative **ppWrapper)
|
||||
{
|
||||
return xpc_qsUnwrapThisImpl(cx,
|
||||
obj,
|
||||
NS_GET_TEMPLATE_IID(T),
|
||||
reinterpret_cast<void **>(ppThis),
|
||||
ppWrapper);
|
||||
}
|
||||
|
||||
JSBool
|
||||
xpc_qsUnwrapThisFromCcxImpl(XPCCallContext &ccx,
|
||||
const nsIID &iid,
|
||||
void **ppThis);
|
||||
|
||||
/**
|
||||
* Alternate implementation of xpc_qsUnwrapThis using information already
|
||||
* present in the given XPCCallContext.
|
||||
*/
|
||||
template <class T>
|
||||
inline JSBool
|
||||
xpc_qsUnwrapThisFromCcx(XPCCallContext &ccx,
|
||||
T **ppThis)
|
||||
{
|
||||
return xpc_qsUnwrapThisFromCcxImpl(ccx, NS_GET_TEMPLATE_IID(T),
|
||||
reinterpret_cast<void **>(ppThis));
|
||||
}
|
||||
|
||||
nsresult
|
||||
xpc_qsUnwrapArgImpl(JSContext *cx, jsval v, const nsIID &iid, void **ppArg);
|
||||
|
||||
/** Convert a jsval to an XPCOM pointer. */
|
||||
template <class T>
|
||||
inline nsresult
|
||||
xpc_qsUnwrapArg(JSContext *cx, jsval v, T **ppArg)
|
||||
{
|
||||
return xpc_qsUnwrapArgImpl(cx, v, NS_GET_TEMPLATE_IID(T),
|
||||
reinterpret_cast<void **>(ppArg));
|
||||
}
|
||||
|
||||
/** Convert an XPCOM pointer to jsval. Return JS_TRUE on success. */
|
||||
JSBool
|
||||
xpc_qsXPCOMObjectToJsval(XPCCallContext &ccx,
|
||||
nsISupports *p,
|
||||
const nsIID &iid,
|
||||
jsval *rval);
|
||||
|
||||
/**
|
||||
* Convert a variant to jsval. Return JS_TRUE on success.
|
||||
*
|
||||
* @a paramNum is used in error messages. XPConnect treats the return
|
||||
* value as a parameter in this regard.
|
||||
*/
|
||||
JSBool
|
||||
xpc_qsVariantToJsval(XPCCallContext &ccx,
|
||||
nsIVariant *p,
|
||||
uintN paramNum,
|
||||
jsval *rval);
|
||||
|
||||
/**
|
||||
* Use this as the setter for readonly attributes. (The IDL readonly
|
||||
* keyword does not map to JSPROP_READONLY. Semantic mismatch.)
|
||||
*
|
||||
* Always fails, with the same error as setting a property that has
|
||||
* JSPROP_GETTER but not JSPROP_SETTER.
|
||||
*/
|
||||
JSBool
|
||||
xpc_qsReadOnlySetter(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
xpc_qsAssertContextOK(JSContext *cx);
|
||||
|
||||
#define XPC_QS_ASSERT_CONTEXT_OK(cx) xpc_qsAssertContextOK(cx)
|
||||
#else
|
||||
#define XPC_QS_ASSERT_CONTEXT_OK(cx) ((void) 0)
|
||||
#endif
|
||||
|
||||
#endif /* xpcquickstubs_h___ */
|
@ -63,7 +63,7 @@ XPCThrower::Throw(nsresult rv, JSContext* cx)
|
||||
*/
|
||||
// static
|
||||
JSBool
|
||||
XPCThrower::CheckForPendingException(nsresult result, XPCCallContext &ccx)
|
||||
XPCThrower::CheckForPendingException(nsresult result, JSContext *cx)
|
||||
{
|
||||
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
|
||||
if(!xpc)
|
||||
@ -79,8 +79,8 @@ XPCThrower::CheckForPendingException(nsresult result, XPCCallContext &ccx)
|
||||
if(NS_FAILED(e->GetResult(&e_result)) || e_result != result)
|
||||
return JS_FALSE;
|
||||
|
||||
if(!ThrowExceptionObject(ccx, e))
|
||||
JS_ReportOutOfMemory(ccx);
|
||||
if(!ThrowExceptionObject(cx, e))
|
||||
JS_ReportOutOfMemory(cx);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,20 @@ XPCWrappedNativeProto::Init(
|
||||
|
||||
JSBool ok = mJSProtoObject && JS_SetPrivate(ccx, mJSProtoObject, this);
|
||||
|
||||
if(ok && scriptableCreateInfo)
|
||||
{
|
||||
nsIXPCScriptable *callback = scriptableCreateInfo->GetCallback();
|
||||
if(callback)
|
||||
{
|
||||
nsresult rv = callback->PostCreatePrototype(ccx, mJSProtoObject);
|
||||
if(NS_FAILED(rv))
|
||||
{
|
||||
XPCThrower::Throw(rv, ccx);
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_ReportShadowedMembers(mSet, nsnull, this);
|
||||
|
||||
return ok;
|
||||
|
@ -32,8 +32,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=390488
|
||||
return stack;
|
||||
}
|
||||
|
||||
var correctStack1 = " 1. checkForStacks 2. onclick 3. dispatchEvent 4. simulateClick";
|
||||
|
||||
function getStack2() {
|
||||
var stack = new Error().stack;
|
||||
// Remove the two lines due to calling this
|
||||
@ -46,10 +44,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=390488
|
||||
0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
$("testdiv").dispatchEvent(evt);
|
||||
}
|
||||
|
||||
|
||||
function matches(s, p, name) {
|
||||
ok(s.match(p) != null, name,
|
||||
"got " + uneval(s) + ", expected a string matching " + uneval(p));
|
||||
}
|
||||
|
||||
function checkForStacks() {
|
||||
is(getStack1(), correctStack1,
|
||||
"Stack from walking caller chain should be correct");
|
||||
matches(getStack1(), /checkForStacks .* onclick .* simulateClick/,
|
||||
"Stack from walking caller chain should be correct");
|
||||
isnot(getStack2().indexOf("simulateClick()@"), -1,
|
||||
"Stack from |new Error().stack| should include simulateClick");
|
||||
}
|
||||
|
504
other-licenses/ply/COPYING
Normal file
504
other-licenses/ply/COPYING
Normal file
@ -0,0 +1,504 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
9
other-licenses/ply/README
Normal file
9
other-licenses/ply/README
Normal file
@ -0,0 +1,9 @@
|
||||
David Beazley's PLY (Python Lex-Yacc)
|
||||
http://www.dabeaz.com/ply/
|
||||
|
||||
Licensed under the GPL (v2.1 or later).
|
||||
|
||||
This directory contains just the code and license from PLY version 2.5;
|
||||
the full distribution (see the URL) also contains examples, tests,
|
||||
documentation, and a longer README.
|
||||
|
4
other-licenses/ply/ply/__init__.py
Normal file
4
other-licenses/ply/ply/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# PLY package
|
||||
# Author: David Beazley (dave@dabeaz.com)
|
||||
|
||||
__all__ = ['lex','yacc']
|
896
other-licenses/ply/ply/lex.py
Normal file
896
other-licenses/ply/ply/lex.py
Normal file
@ -0,0 +1,896 @@
|
||||
# -----------------------------------------------------------------------------
|
||||
# ply: lex.py
|
||||
#
|
||||
# Author: David M. Beazley (dave@dabeaz.com)
|
||||
#
|
||||
# Copyright (C) 2001-2008, David M. Beazley
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# See the file COPYING for a complete copy of the LGPL.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
__version__ = "2.5"
|
||||
__tabversion__ = "2.4" # Version of table file used
|
||||
|
||||
import re, sys, types, copy, os
|
||||
|
||||
# This regular expression is used to match valid token names
|
||||
_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$')
|
||||
|
||||
# _INSTANCETYPE sets the valid set of instance types recognized
|
||||
# by PLY when lexers are defined by a class. In order to maintain
|
||||
# backwards compatibility with Python-2.0, we have to check for
|
||||
# the existence of ObjectType.
|
||||
|
||||
try:
|
||||
_INSTANCETYPE = (types.InstanceType, types.ObjectType)
|
||||
except AttributeError:
|
||||
_INSTANCETYPE = types.InstanceType
|
||||
class object: pass # Note: needed if no new-style classes present
|
||||
|
||||
# Exception thrown when invalid token encountered and no default error
|
||||
# handler is defined.
|
||||
|
||||
class LexError(Exception):
|
||||
def __init__(self,message,s):
|
||||
self.args = (message,)
|
||||
self.text = s
|
||||
|
||||
# An object used to issue one-time warning messages for various features
|
||||
|
||||
class LexWarning(object):
|
||||
def __init__(self):
|
||||
self.warned = 0
|
||||
def __call__(self,msg):
|
||||
if not self.warned:
|
||||
sys.stderr.write("ply.lex: Warning: " + msg+"\n")
|
||||
self.warned = 1
|
||||
|
||||
_SkipWarning = LexWarning() # Warning for use of t.skip() on tokens
|
||||
|
||||
# Token class. This class is used to represent the tokens produced.
|
||||
class LexToken(object):
|
||||
def __str__(self):
|
||||
return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos)
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
def skip(self,n):
|
||||
self.lexer.skip(n)
|
||||
_SkipWarning("Calling t.skip() on a token is deprecated. Please use t.lexer.skip()")
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Lexer class
|
||||
#
|
||||
# This class encapsulates all of the methods and data associated with a lexer.
|
||||
#
|
||||
# input() - Store a new string in the lexer
|
||||
# token() - Get the next token
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
class Lexer:
|
||||
def __init__(self):
|
||||
self.lexre = None # Master regular expression. This is a list of
|
||||
# tuples (re,findex) where re is a compiled
|
||||
# regular expression and findex is a list
|
||||
# mapping regex group numbers to rules
|
||||
self.lexretext = None # Current regular expression strings
|
||||
self.lexstatere = {} # Dictionary mapping lexer states to master regexs
|
||||
self.lexstateretext = {} # Dictionary mapping lexer states to regex strings
|
||||
self.lexstaterenames = {} # Dictionary mapping lexer states to symbol names
|
||||
self.lexstate = "INITIAL" # Current lexer state
|
||||
self.lexstatestack = [] # Stack of lexer states
|
||||
self.lexstateinfo = None # State information
|
||||
self.lexstateignore = {} # Dictionary of ignored characters for each state
|
||||
self.lexstateerrorf = {} # Dictionary of error functions for each state
|
||||
self.lexreflags = 0 # Optional re compile flags
|
||||
self.lexdata = None # Actual input data (as a string)
|
||||
self.lexpos = 0 # Current position in input text
|
||||
self.lexlen = 0 # Length of the input text
|
||||
self.lexerrorf = None # Error rule (if any)
|
||||
self.lextokens = None # List of valid tokens
|
||||
self.lexignore = "" # Ignored characters
|
||||
self.lexliterals = "" # Literal characters that can be passed through
|
||||
self.lexmodule = None # Module
|
||||
self.lineno = 1 # Current line number
|
||||
self.lexdebug = 0 # Debugging mode
|
||||
self.lexoptimize = 0 # Optimized mode
|
||||
|
||||
def clone(self,object=None):
|
||||
c = copy.copy(self)
|
||||
|
||||
# If the object parameter has been supplied, it means we are attaching the
|
||||
# lexer to a new object. In this case, we have to rebind all methods in
|
||||
# the lexstatere and lexstateerrorf tables.
|
||||
|
||||
if object:
|
||||
newtab = { }
|
||||
for key, ritem in self.lexstatere.items():
|
||||
newre = []
|
||||
for cre, findex in ritem:
|
||||
newfindex = []
|
||||
for f in findex:
|
||||
if not f or not f[0]:
|
||||
newfindex.append(f)
|
||||
continue
|
||||
newfindex.append((getattr(object,f[0].__name__),f[1]))
|
||||
newre.append((cre,newfindex))
|
||||
newtab[key] = newre
|
||||
c.lexstatere = newtab
|
||||
c.lexstateerrorf = { }
|
||||
for key, ef in self.lexstateerrorf.items():
|
||||
c.lexstateerrorf[key] = getattr(object,ef.__name__)
|
||||
c.lexmodule = object
|
||||
return c
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# writetab() - Write lexer information to a table file
|
||||
# ------------------------------------------------------------
|
||||
def writetab(self,tabfile,outputdir=""):
|
||||
if isinstance(tabfile,types.ModuleType):
|
||||
return
|
||||
basetabfilename = tabfile.split(".")[-1]
|
||||
filename = os.path.join(outputdir,basetabfilename)+".py"
|
||||
tf = open(filename,"w")
|
||||
tf.write("# %s.py. This file automatically created by PLY (version %s). Don't edit!\n" % (tabfile,__version__))
|
||||
tf.write("_lextokens = %s\n" % repr(self.lextokens))
|
||||
tf.write("_lexreflags = %s\n" % repr(self.lexreflags))
|
||||
tf.write("_lexliterals = %s\n" % repr(self.lexliterals))
|
||||
tf.write("_lexstateinfo = %s\n" % repr(self.lexstateinfo))
|
||||
|
||||
tabre = { }
|
||||
# Collect all functions in the initial state
|
||||
initial = self.lexstatere["INITIAL"]
|
||||
initialfuncs = []
|
||||
for part in initial:
|
||||
for f in part[1]:
|
||||
if f and f[0]:
|
||||
initialfuncs.append(f)
|
||||
|
||||
for key, lre in self.lexstatere.items():
|
||||
titem = []
|
||||
for i in range(len(lre)):
|
||||
titem.append((self.lexstateretext[key][i],_funcs_to_names(lre[i][1],self.lexstaterenames[key][i])))
|
||||
tabre[key] = titem
|
||||
|
||||
tf.write("_lexstatere = %s\n" % repr(tabre))
|
||||
tf.write("_lexstateignore = %s\n" % repr(self.lexstateignore))
|
||||
|
||||
taberr = { }
|
||||
for key, ef in self.lexstateerrorf.items():
|
||||
if ef:
|
||||
taberr[key] = ef.__name__
|
||||
else:
|
||||
taberr[key] = None
|
||||
tf.write("_lexstateerrorf = %s\n" % repr(taberr))
|
||||
tf.close()
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# readtab() - Read lexer information from a tab file
|
||||
# ------------------------------------------------------------
|
||||
def readtab(self,tabfile,fdict):
|
||||
if isinstance(tabfile,types.ModuleType):
|
||||
lextab = tabfile
|
||||
else:
|
||||
exec "import %s as lextab" % tabfile
|
||||
self.lextokens = lextab._lextokens
|
||||
self.lexreflags = lextab._lexreflags
|
||||
self.lexliterals = lextab._lexliterals
|
||||
self.lexstateinfo = lextab._lexstateinfo
|
||||
self.lexstateignore = lextab._lexstateignore
|
||||
self.lexstatere = { }
|
||||
self.lexstateretext = { }
|
||||
for key,lre in lextab._lexstatere.items():
|
||||
titem = []
|
||||
txtitem = []
|
||||
for i in range(len(lre)):
|
||||
titem.append((re.compile(lre[i][0],lextab._lexreflags),_names_to_funcs(lre[i][1],fdict)))
|
||||
txtitem.append(lre[i][0])
|
||||
self.lexstatere[key] = titem
|
||||
self.lexstateretext[key] = txtitem
|
||||
self.lexstateerrorf = { }
|
||||
for key,ef in lextab._lexstateerrorf.items():
|
||||
self.lexstateerrorf[key] = fdict[ef]
|
||||
self.begin('INITIAL')
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# input() - Push a new string into the lexer
|
||||
# ------------------------------------------------------------
|
||||
def input(self,s):
|
||||
# Pull off the first character to see if s looks like a string
|
||||
c = s[:1]
|
||||
if not (isinstance(c,types.StringType) or isinstance(c,types.UnicodeType)):
|
||||
raise ValueError, "Expected a string"
|
||||
self.lexdata = s
|
||||
self.lexpos = 0
|
||||
self.lexlen = len(s)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# begin() - Changes the lexing state
|
||||
# ------------------------------------------------------------
|
||||
def begin(self,state):
|
||||
if not self.lexstatere.has_key(state):
|
||||
raise ValueError, "Undefined state"
|
||||
self.lexre = self.lexstatere[state]
|
||||
self.lexretext = self.lexstateretext[state]
|
||||
self.lexignore = self.lexstateignore.get(state,"")
|
||||
self.lexerrorf = self.lexstateerrorf.get(state,None)
|
||||
self.lexstate = state
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# push_state() - Changes the lexing state and saves old on stack
|
||||
# ------------------------------------------------------------
|
||||
def push_state(self,state):
|
||||
self.lexstatestack.append(self.lexstate)
|
||||
self.begin(state)
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# pop_state() - Restores the previous state
|
||||
# ------------------------------------------------------------
|
||||
def pop_state(self):
|
||||
self.begin(self.lexstatestack.pop())
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# current_state() - Returns the current lexing state
|
||||
# ------------------------------------------------------------
|
||||
def current_state(self):
|
||||
return self.lexstate
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# skip() - Skip ahead n characters
|
||||
# ------------------------------------------------------------
|
||||
def skip(self,n):
|
||||
self.lexpos += n
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# token() - Return the next token from the Lexer
|
||||
#
|
||||
# Note: This function has been carefully implemented to be as fast
|
||||
# as possible. Don't make changes unless you really know what
|
||||
# you are doing
|
||||
# ------------------------------------------------------------
|
||||
def token(self):
|
||||
# Make local copies of frequently referenced attributes
|
||||
lexpos = self.lexpos
|
||||
lexlen = self.lexlen
|
||||
lexignore = self.lexignore
|
||||
lexdata = self.lexdata
|
||||
|
||||
while lexpos < lexlen:
|
||||
# This code provides some short-circuit code for whitespace, tabs, and other ignored characters
|
||||
if lexdata[lexpos] in lexignore:
|
||||
lexpos += 1
|
||||
continue
|
||||
|
||||
# Look for a regular expression match
|
||||
for lexre,lexindexfunc in self.lexre:
|
||||
m = lexre.match(lexdata,lexpos)
|
||||
if not m: continue
|
||||
|
||||
# Create a token for return
|
||||
tok = LexToken()
|
||||
tok.value = m.group()
|
||||
tok.lineno = self.lineno
|
||||
tok.lexpos = lexpos
|
||||
|
||||
i = m.lastindex
|
||||
func,tok.type = lexindexfunc[i]
|
||||
|
||||
if not func:
|
||||
# If no token type was set, it's an ignored token
|
||||
if tok.type:
|
||||
self.lexpos = m.end()
|
||||
return tok
|
||||
else:
|
||||
lexpos = m.end()
|
||||
break
|
||||
|
||||
lexpos = m.end()
|
||||
|
||||
# if func not callable, it means it's an ignored token
|
||||
if not callable(func):
|
||||
break
|
||||
|
||||
# If token is processed by a function, call it
|
||||
|
||||
tok.lexer = self # Set additional attributes useful in token rules
|
||||
self.lexmatch = m
|
||||
self.lexpos = lexpos
|
||||
|
||||
newtok = func(tok)
|
||||
|
||||
# Every function must return a token, if nothing, we just move to next token
|
||||
if not newtok:
|
||||
lexpos = self.lexpos # This is here in case user has updated lexpos.
|
||||
lexignore = self.lexignore # This is here in case there was a state change
|
||||
break
|
||||
|
||||
# Verify type of the token. If not in the token map, raise an error
|
||||
if not self.lexoptimize:
|
||||
if not self.lextokens.has_key(newtok.type):
|
||||
raise LexError, ("%s:%d: Rule '%s' returned an unknown token type '%s'" % (
|
||||
func.func_code.co_filename, func.func_code.co_firstlineno,
|
||||
func.__name__, newtok.type),lexdata[lexpos:])
|
||||
|
||||
return newtok
|
||||
else:
|
||||
# No match, see if in literals
|
||||
if lexdata[lexpos] in self.lexliterals:
|
||||
tok = LexToken()
|
||||
tok.value = lexdata[lexpos]
|
||||
tok.lineno = self.lineno
|
||||
tok.type = tok.value
|
||||
tok.lexpos = lexpos
|
||||
self.lexpos = lexpos + 1
|
||||
return tok
|
||||
|
||||
# No match. Call t_error() if defined.
|
||||
if self.lexerrorf:
|
||||
tok = LexToken()
|
||||
tok.value = self.lexdata[lexpos:]
|
||||
tok.lineno = self.lineno
|
||||
tok.type = "error"
|
||||
tok.lexer = self
|
||||
tok.lexpos = lexpos
|
||||
self.lexpos = lexpos
|
||||
newtok = self.lexerrorf(tok)
|
||||
if lexpos == self.lexpos:
|
||||
# Error method didn't change text position at all. This is an error.
|
||||
raise LexError, ("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:])
|
||||
lexpos = self.lexpos
|
||||
if not newtok: continue
|
||||
return newtok
|
||||
|
||||
self.lexpos = lexpos
|
||||
raise LexError, ("Illegal character '%s' at index %d" % (lexdata[lexpos],lexpos), lexdata[lexpos:])
|
||||
|
||||
self.lexpos = lexpos + 1
|
||||
if self.lexdata is None:
|
||||
raise RuntimeError, "No input string given with input()"
|
||||
return None
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# _validate_file()
|
||||
#
|
||||
# This checks to see if there are duplicated t_rulename() functions or strings
|
||||
# in the parser input file. This is done using a simple regular expression
|
||||
# match on each line in the given file. If the file can't be located or opened,
|
||||
# a true result is returned by default.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _validate_file(filename):
|
||||
import os.path
|
||||
base,ext = os.path.splitext(filename)
|
||||
if ext != '.py': return 1 # No idea what the file is. Return OK
|
||||
|
||||
try:
|
||||
f = open(filename)
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
except IOError:
|
||||
return 1 # Couldn't find the file. Don't worry about it
|
||||
|
||||
fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(')
|
||||
sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=')
|
||||
|
||||
counthash = { }
|
||||
linen = 1
|
||||
noerror = 1
|
||||
for l in lines:
|
||||
m = fre.match(l)
|
||||
if not m:
|
||||
m = sre.match(l)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
prev = counthash.get(name)
|
||||
if not prev:
|
||||
counthash[name] = linen
|
||||
else:
|
||||
print >>sys.stderr, "%s:%d: Rule %s redefined. Previously defined on line %d" % (filename,linen,name,prev)
|
||||
noerror = 0
|
||||
linen += 1
|
||||
return noerror
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# _funcs_to_names()
|
||||
#
|
||||
# Given a list of regular expression functions, this converts it to a list
|
||||
# suitable for output to a table file
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _funcs_to_names(funclist,namelist):
|
||||
result = []
|
||||
for f,name in zip(funclist,namelist):
|
||||
if f and f[0]:
|
||||
result.append((name, f[1]))
|
||||
else:
|
||||
result.append(f)
|
||||
return result
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# _names_to_funcs()
|
||||
#
|
||||
# Given a list of regular expression function names, this converts it back to
|
||||
# functions.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _names_to_funcs(namelist,fdict):
|
||||
result = []
|
||||
for n in namelist:
|
||||
if n and n[0]:
|
||||
result.append((fdict[n[0]],n[1]))
|
||||
else:
|
||||
result.append(n)
|
||||
return result
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# _form_master_re()
|
||||
#
|
||||
# This function takes a list of all of the regex components and attempts to
|
||||
# form the master regular expression. Given limitations in the Python re
|
||||
# module, it may be necessary to break the master regex into separate expressions.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _form_master_re(relist,reflags,ldict,toknames):
|
||||
if not relist: return []
|
||||
regex = "|".join(relist)
|
||||
try:
|
||||
lexre = re.compile(regex,re.VERBOSE | reflags)
|
||||
|
||||
# Build the index to function map for the matching engine
|
||||
lexindexfunc = [ None ] * (max(lexre.groupindex.values())+1)
|
||||
lexindexnames = lexindexfunc[:]
|
||||
|
||||
for f,i in lexre.groupindex.items():
|
||||
handle = ldict.get(f,None)
|
||||
if type(handle) in (types.FunctionType, types.MethodType):
|
||||
lexindexfunc[i] = (handle,toknames[f])
|
||||
lexindexnames[i] = f
|
||||
elif handle is not None:
|
||||
lexindexnames[i] = f
|
||||
if f.find("ignore_") > 0:
|
||||
lexindexfunc[i] = (None,None)
|
||||
else:
|
||||
lexindexfunc[i] = (None, toknames[f])
|
||||
|
||||
return [(lexre,lexindexfunc)],[regex],[lexindexnames]
|
||||
except Exception,e:
|
||||
m = int(len(relist)/2)
|
||||
if m == 0: m = 1
|
||||
llist, lre, lnames = _form_master_re(relist[:m],reflags,ldict,toknames)
|
||||
rlist, rre, rnames = _form_master_re(relist[m:],reflags,ldict,toknames)
|
||||
return llist+rlist, lre+rre, lnames+rnames
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# def _statetoken(s,names)
|
||||
#
|
||||
# Given a declaration name s of the form "t_" and a dictionary whose keys are
|
||||
# state names, this function returns a tuple (states,tokenname) where states
|
||||
# is a tuple of state names and tokenname is the name of the token. For example,
|
||||
# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM')
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def _statetoken(s,names):
|
||||
nonstate = 1
|
||||
parts = s.split("_")
|
||||
for i in range(1,len(parts)):
|
||||
if not names.has_key(parts[i]) and parts[i] != 'ANY': break
|
||||
if i > 1:
|
||||
states = tuple(parts[1:i])
|
||||
else:
|
||||
states = ('INITIAL',)
|
||||
|
||||
if 'ANY' in states:
|
||||
states = tuple(names.keys())
|
||||
|
||||
tokenname = "_".join(parts[i:])
|
||||
return (states,tokenname)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# lex(module)
|
||||
#
|
||||
# Build all of the regular expression rules from definitions in the supplied module
|
||||
# -----------------------------------------------------------------------------
|
||||
def lex(module=None,object=None,debug=0,optimize=0,lextab="lextab",reflags=0,nowarn=0,outputdir=""):
|
||||
global lexer
|
||||
ldict = None
|
||||
stateinfo = { 'INITIAL' : 'inclusive'}
|
||||
error = 0
|
||||
files = { }
|
||||
lexobj = Lexer()
|
||||
lexobj.lexdebug = debug
|
||||
lexobj.lexoptimize = optimize
|
||||
global token,input
|
||||
|
||||
if nowarn: warn = 0
|
||||
else: warn = 1
|
||||
|
||||
if object: module = object
|
||||
|
||||
if module:
|
||||
# User supplied a module object.
|
||||
if isinstance(module, types.ModuleType):
|
||||
ldict = module.__dict__
|
||||
elif isinstance(module, _INSTANCETYPE):
|
||||
_items = [(k,getattr(module,k)) for k in dir(module)]
|
||||
ldict = { }
|
||||
for (i,v) in _items:
|
||||
ldict[i] = v
|
||||
else:
|
||||
raise ValueError,"Expected a module or instance"
|
||||
lexobj.lexmodule = module
|
||||
|
||||
else:
|
||||
# No module given. We might be able to get information from the caller.
|
||||
try:
|
||||
raise RuntimeError
|
||||
except RuntimeError:
|
||||
e,b,t = sys.exc_info()
|
||||
f = t.tb_frame
|
||||
f = f.f_back # Walk out to our calling function
|
||||
if f.f_globals is f.f_locals: # Collect global and local variations from caller
|
||||
ldict = f.f_globals
|
||||
else:
|
||||
ldict = f.f_globals.copy()
|
||||
ldict.update(f.f_locals)
|
||||
|
||||
if optimize and lextab:
|
||||
try:
|
||||
lexobj.readtab(lextab,ldict)
|
||||
token = lexobj.token
|
||||
input = lexobj.input
|
||||
lexer = lexobj
|
||||
return lexobj
|
||||
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
# Get the tokens, states, and literals variables (if any)
|
||||
|
||||
tokens = ldict.get("tokens",None)
|
||||
states = ldict.get("states",None)
|
||||
literals = ldict.get("literals","")
|
||||
|
||||
if not tokens:
|
||||
raise SyntaxError,"lex: module does not define 'tokens'"
|
||||
|
||||
if not (isinstance(tokens,types.ListType) or isinstance(tokens,types.TupleType)):
|
||||
raise SyntaxError,"lex: tokens must be a list or tuple."
|
||||
|
||||
# Build a dictionary of valid token names
|
||||
lexobj.lextokens = { }
|
||||
if not optimize:
|
||||
for n in tokens:
|
||||
if not _is_identifier.match(n):
|
||||
print >>sys.stderr, "lex: Bad token name '%s'" % n
|
||||
error = 1
|
||||
if warn and lexobj.lextokens.has_key(n):
|
||||
print >>sys.stderr, "lex: Warning. Token '%s' multiply defined." % n
|
||||
lexobj.lextokens[n] = None
|
||||
else:
|
||||
for n in tokens: lexobj.lextokens[n] = None
|
||||
|
||||
if debug:
|
||||
print "lex: tokens = '%s'" % lexobj.lextokens.keys()
|
||||
|
||||
try:
|
||||
for c in literals:
|
||||
if not (isinstance(c,types.StringType) or isinstance(c,types.UnicodeType)) or len(c) > 1:
|
||||
print >>sys.stderr, "lex: Invalid literal %s. Must be a single character" % repr(c)
|
||||
error = 1
|
||||
continue
|
||||
|
||||
except TypeError:
|
||||
print >>sys.stderr, "lex: Invalid literals specification. literals must be a sequence of characters."
|
||||
error = 1
|
||||
|
||||
lexobj.lexliterals = literals
|
||||
|
||||
# Build statemap
|
||||
if states:
|
||||
if not (isinstance(states,types.TupleType) or isinstance(states,types.ListType)):
|
||||
print >>sys.stderr, "lex: states must be defined as a tuple or list."
|
||||
error = 1
|
||||
else:
|
||||
for s in states:
|
||||
if not isinstance(s,types.TupleType) or len(s) != 2:
|
||||
print >>sys.stderr, "lex: invalid state specifier %s. Must be a tuple (statename,'exclusive|inclusive')" % repr(s)
|
||||
error = 1
|
||||
continue
|
||||
name, statetype = s
|
||||
if not isinstance(name,types.StringType):
|
||||
print >>sys.stderr, "lex: state name %s must be a string" % repr(name)
|
||||
error = 1
|
||||
continue
|
||||
if not (statetype == 'inclusive' or statetype == 'exclusive'):
|
||||
print >>sys.stderr, "lex: state type for state %s must be 'inclusive' or 'exclusive'" % name
|
||||
error = 1
|
||||
continue
|
||||
if stateinfo.has_key(name):
|
||||
print >>sys.stderr, "lex: state '%s' already defined." % name
|
||||
error = 1
|
||||
continue
|
||||
stateinfo[name] = statetype
|
||||
|
||||
# Get a list of symbols with the t_ or s_ prefix
|
||||
tsymbols = [f for f in ldict.keys() if f[:2] == 't_' ]
|
||||
|
||||
# Now build up a list of functions and a list of strings
|
||||
|
||||
funcsym = { } # Symbols defined as functions
|
||||
strsym = { } # Symbols defined as strings
|
||||
toknames = { } # Mapping of symbols to token names
|
||||
|
||||
for s in stateinfo.keys():
|
||||
funcsym[s] = []
|
||||
strsym[s] = []
|
||||
|
||||
ignore = { } # Ignore strings by state
|
||||
errorf = { } # Error functions by state
|
||||
|
||||
if len(tsymbols) == 0:
|
||||
raise SyntaxError,"lex: no rules of the form t_rulename are defined."
|
||||
|
||||
for f in tsymbols:
|
||||
t = ldict[f]
|
||||
states, tokname = _statetoken(f,stateinfo)
|
||||
toknames[f] = tokname
|
||||
|
||||
if callable(t):
|
||||
for s in states: funcsym[s].append((f,t))
|
||||
elif (isinstance(t, types.StringType) or isinstance(t,types.UnicodeType)):
|
||||
for s in states: strsym[s].append((f,t))
|
||||
else:
|
||||
print >>sys.stderr, "lex: %s not defined as a function or string" % f
|
||||
error = 1
|
||||
|
||||
# Sort the functions by line number
|
||||
for f in funcsym.values():
|
||||
f.sort(lambda x,y: cmp(x[1].func_code.co_firstlineno,y[1].func_code.co_firstlineno))
|
||||
|
||||
# Sort the strings by regular expression length
|
||||
for s in strsym.values():
|
||||
s.sort(lambda x,y: (len(x[1]) < len(y[1])) - (len(x[1]) > len(y[1])))
|
||||
|
||||
regexs = { }
|
||||
|
||||
# Build the master regular expressions
|
||||
for state in stateinfo.keys():
|
||||
regex_list = []
|
||||
|
||||
# Add rules defined by functions first
|
||||
for fname, f in funcsym[state]:
|
||||
line = f.func_code.co_firstlineno
|
||||
file = f.func_code.co_filename
|
||||
files[file] = None
|
||||
tokname = toknames[fname]
|
||||
|
||||
ismethod = isinstance(f, types.MethodType)
|
||||
|
||||
if not optimize:
|
||||
nargs = f.func_code.co_argcount
|
||||
if ismethod:
|
||||
reqargs = 2
|
||||
else:
|
||||
reqargs = 1
|
||||
if nargs > reqargs:
|
||||
print >>sys.stderr, "%s:%d: Rule '%s' has too many arguments." % (file,line,f.__name__)
|
||||
error = 1
|
||||
continue
|
||||
|
||||
if nargs < reqargs:
|
||||
print >>sys.stderr, "%s:%d: Rule '%s' requires an argument." % (file,line,f.__name__)
|
||||
error = 1
|
||||
continue
|
||||
|
||||
if tokname == 'ignore':
|
||||
print >>sys.stderr, "%s:%d: Rule '%s' must be defined as a string." % (file,line,f.__name__)
|
||||
error = 1
|
||||
continue
|
||||
|
||||
if tokname == 'error':
|
||||
errorf[state] = f
|
||||
continue
|
||||
|
||||
if f.__doc__:
|
||||
if not optimize:
|
||||
try:
|
||||
c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | reflags)
|
||||
if c.match(""):
|
||||
print >>sys.stderr, "%s:%d: Regular expression for rule '%s' matches empty string." % (file,line,f.__name__)
|
||||
error = 1
|
||||
continue
|
||||
except re.error,e:
|
||||
print >>sys.stderr, "%s:%d: Invalid regular expression for rule '%s'. %s" % (file,line,f.__name__,e)
|
||||
if '#' in f.__doc__:
|
||||
print >>sys.stderr, "%s:%d. Make sure '#' in rule '%s' is escaped with '\\#'." % (file,line, f.__name__)
|
||||
error = 1
|
||||
continue
|
||||
|
||||
if debug:
|
||||
print "lex: Adding rule %s -> '%s' (state '%s')" % (f.__name__,f.__doc__, state)
|
||||
|
||||
# Okay. The regular expression seemed okay. Let's append it to the master regular
|
||||
# expression we're building
|
||||
|
||||
regex_list.append("(?P<%s>%s)" % (fname,f.__doc__))
|
||||
else:
|
||||
print >>sys.stderr, "%s:%d: No regular expression defined for rule '%s'" % (file,line,f.__name__)
|
||||
|
||||
# Now add all of the simple rules
|
||||
for name,r in strsym[state]:
|
||||
tokname = toknames[name]
|
||||
|
||||
if tokname == 'ignore':
|
||||
if "\\" in r:
|
||||
print >>sys.stderr, "lex: Warning. %s contains a literal backslash '\\'" % name
|
||||
ignore[state] = r
|
||||
continue
|
||||
|
||||
if not optimize:
|
||||
if tokname == 'error':
|
||||
raise SyntaxError,"lex: Rule '%s' must be defined as a function" % name
|
||||
error = 1
|
||||
continue
|
||||
|
||||
if not lexobj.lextokens.has_key(tokname) and tokname.find("ignore_") < 0:
|
||||
print >>sys.stderr, "lex: Rule '%s' defined for an unspecified token %s." % (name,tokname)
|
||||
error = 1
|
||||
continue
|
||||
try:
|
||||
c = re.compile("(?P<%s>%s)" % (name,r),re.VERBOSE | reflags)
|
||||
if (c.match("")):
|
||||
print >>sys.stderr, "lex: Regular expression for rule '%s' matches empty string." % name
|
||||
error = 1
|
||||
continue
|
||||
except re.error,e:
|
||||
print >>sys.stderr, "lex: Invalid regular expression for rule '%s'. %s" % (name,e)
|
||||
if '#' in r:
|
||||
print >>sys.stderr, "lex: Make sure '#' in rule '%s' is escaped with '\\#'." % name
|
||||
|
||||
error = 1
|
||||
continue
|
||||
if debug:
|
||||
print "lex: Adding rule %s -> '%s' (state '%s')" % (name,r,state)
|
||||
|
||||
regex_list.append("(?P<%s>%s)" % (name,r))
|
||||
|
||||
if not regex_list:
|
||||
print >>sys.stderr, "lex: No rules defined for state '%s'" % state
|
||||
error = 1
|
||||
|
||||
regexs[state] = regex_list
|
||||
|
||||
|
||||
if not optimize:
|
||||
for f in files.keys():
|
||||
if not _validate_file(f):
|
||||
error = 1
|
||||
|
||||
if error:
|
||||
raise SyntaxError,"lex: Unable to build lexer."
|
||||
|
||||
# From this point forward, we're reasonably confident that we can build the lexer.
|
||||
# No more errors will be generated, but there might be some warning messages.
|
||||
|
||||
# Build the master regular expressions
|
||||
|
||||
for state in regexs.keys():
|
||||
lexre, re_text, re_names = _form_master_re(regexs[state],reflags,ldict,toknames)
|
||||
lexobj.lexstatere[state] = lexre
|
||||
lexobj.lexstateretext[state] = re_text
|
||||
lexobj.lexstaterenames[state] = re_names
|
||||
if debug:
|
||||
for i in range(len(re_text)):
|
||||
print "lex: state '%s'. regex[%d] = '%s'" % (state, i, re_text[i])
|
||||
|
||||
# For inclusive states, we need to add the INITIAL state
|
||||
for state,type in stateinfo.items():
|
||||
if state != "INITIAL" and type == 'inclusive':
|
||||
lexobj.lexstatere[state].extend(lexobj.lexstatere['INITIAL'])
|
||||
lexobj.lexstateretext[state].extend(lexobj.lexstateretext['INITIAL'])
|
||||
lexobj.lexstaterenames[state].extend(lexobj.lexstaterenames['INITIAL'])
|
||||
|
||||
lexobj.lexstateinfo = stateinfo
|
||||
lexobj.lexre = lexobj.lexstatere["INITIAL"]
|
||||
lexobj.lexretext = lexobj.lexstateretext["INITIAL"]
|
||||
|
||||
# Set up ignore variables
|
||||
lexobj.lexstateignore = ignore
|
||||
lexobj.lexignore = lexobj.lexstateignore.get("INITIAL","")
|
||||
|
||||
# Set up error functions
|
||||
lexobj.lexstateerrorf = errorf
|
||||
lexobj.lexerrorf = errorf.get("INITIAL",None)
|
||||
if warn and not lexobj.lexerrorf:
|
||||
print >>sys.stderr, "lex: Warning. no t_error rule is defined."
|
||||
|
||||
# Check state information for ignore and error rules
|
||||
for s,stype in stateinfo.items():
|
||||
if stype == 'exclusive':
|
||||
if warn and not errorf.has_key(s):
|
||||
print >>sys.stderr, "lex: Warning. no error rule is defined for exclusive state '%s'" % s
|
||||
if warn and not ignore.has_key(s) and lexobj.lexignore:
|
||||
print >>sys.stderr, "lex: Warning. no ignore rule is defined for exclusive state '%s'" % s
|
||||
elif stype == 'inclusive':
|
||||
if not errorf.has_key(s):
|
||||
errorf[s] = errorf.get("INITIAL",None)
|
||||
if not ignore.has_key(s):
|
||||
ignore[s] = ignore.get("INITIAL","")
|
||||
|
||||
|
||||
# Create global versions of the token() and input() functions
|
||||
token = lexobj.token
|
||||
input = lexobj.input
|
||||
lexer = lexobj
|
||||
|
||||
# If in optimize mode, we write the lextab
|
||||
if lextab and optimize:
|
||||
lexobj.writetab(lextab,outputdir)
|
||||
|
||||
return lexobj
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# runmain()
|
||||
#
|
||||
# This runs the lexer as a main program
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def runmain(lexer=None,data=None):
|
||||
if not data:
|
||||
try:
|
||||
filename = sys.argv[1]
|
||||
f = open(filename)
|
||||
data = f.read()
|
||||
f.close()
|
||||
except IndexError:
|
||||
print "Reading from standard input (type EOF to end):"
|
||||
data = sys.stdin.read()
|
||||
|
||||
if lexer:
|
||||
_input = lexer.input
|
||||
else:
|
||||
_input = input
|
||||
_input(data)
|
||||
if lexer:
|
||||
_token = lexer.token
|
||||
else:
|
||||
_token = token
|
||||
|
||||
while 1:
|
||||
tok = _token()
|
||||
if not tok: break
|
||||
print "(%s,%r,%d,%d)" % (tok.type, tok.value, tok.lineno,tok.lexpos)
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# @TOKEN(regex)
|
||||
#
|
||||
# This decorator function can be used to set the regex expression on a function
|
||||
# when its docstring might need to be set in an alternative way
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
def TOKEN(r):
|
||||
def set_doc(f):
|
||||
if callable(r):
|
||||
f.__doc__ = r.__doc__
|
||||
else:
|
||||
f.__doc__ = r
|
||||
return f
|
||||
return set_doc
|
||||
|
||||
# Alternative spelling of the TOKEN decorator
|
||||
Token = TOKEN
|
||||
|
2895
other-licenses/ply/ply/yacc.py
Normal file
2895
other-licenses/ply/ply/yacc.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -474,6 +474,14 @@ mozStorageStatementWrapper::InnerObject(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void postCreatePrototype (in JSContextPtr cx, in JSObjectPtr proto); */
|
||||
NS_IMETHODIMP
|
||||
mozStorageStatementWrapper::PostCreatePrototype(JSContext * cx,
|
||||
JSObject * proto)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
****
|
||||
**** mozStorageStatementRow
|
||||
@ -739,6 +747,13 @@ mozStorageStatementRow::InnerObject(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void postCreatePrototype (in JSContextPtr cx, in JSObjectPtr proto); */
|
||||
NS_IMETHODIMP
|
||||
mozStorageStatementRow::PostCreatePrototype(JSContext * cx, JSObject * proto)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
****
|
||||
**** mozStorageStatementParams
|
||||
@ -1019,3 +1034,9 @@ mozStorageStatementParams::InnerObject(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* void postCreatePrototype (in JSContextPtr cx, in JSObjectPtr proto); */
|
||||
NS_IMETHODIMP
|
||||
mozStorageStatementParams::PostCreatePrototype(JSContext * cx, JSObject * proto)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -44,13 +44,6 @@
|
||||
#include "nsRect.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
// nsIDOMEvent contains a long enum which includes a member called ERROR,
|
||||
// which conflicts with something that Windows defines somewhere.
|
||||
// So, undefine it:
|
||||
#ifdef WIN32
|
||||
#undef ERROR
|
||||
#endif
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIDOMKeyEvent.h"
|
||||
|
444
xpcom/idl-parser/header.py
Normal file
444
xpcom/idl-parser/header.py
Normal file
@ -0,0 +1,444 @@
|
||||
#!/usr/bin/env python
|
||||
# header.py - Generate C++ header files from IDL.
|
||||
#
|
||||
# ***** 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 code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2008
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Benjamin Smedberg <benjamin@smedbergs.us>
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
"""Print a C++ header file for the IDL files specified on the command line"""
|
||||
|
||||
import sys, os.path, re, xpidl
|
||||
|
||||
printdoccomments = False
|
||||
|
||||
if printdoccomments:
|
||||
def printComments(fd, clist, indent):
|
||||
for c in clist:
|
||||
fd.write("%s%s\n" % (indent, c))
|
||||
else:
|
||||
def printComments(fd, clist, indent):
|
||||
pass
|
||||
|
||||
def firstCap(str):
|
||||
return str[0].upper() + str[1:]
|
||||
|
||||
def attributeParamName(a):
|
||||
return "a" + firstCap(a.name)
|
||||
|
||||
def attributeNativeName(a, getter):
|
||||
binaryname = a.binaryname is not None and a.binaryname or firstCap(a.name)
|
||||
return "%s%s" % (getter and 'Get' or 'Set', binaryname)
|
||||
|
||||
def attributeParamlist(a, getter):
|
||||
return "%s%s" % (a.realtype.nativeType(getter and 'out' or 'in'),
|
||||
attributeParamName(a))
|
||||
|
||||
def attributeAsNative(a, getter):
|
||||
scriptable = a.isScriptable() and "NS_SCRIPTABLE " or ""
|
||||
params = {'scriptable': scriptable,
|
||||
'binaryname': attributeNativeName(a, getter),
|
||||
'paramlist': attributeParamlist(a, getter)}
|
||||
return "%(scriptable)sNS_IMETHOD %(binaryname)s(%(paramlist)s)" % params
|
||||
|
||||
def methodNativeName(m):
|
||||
return m.binaryname is not None and m.binaryname or firstCap(m.name)
|
||||
|
||||
def methodReturnType(m, macro):
|
||||
"""macro should be NS_IMETHOD or NS_IMETHODIMP"""
|
||||
if m.notxpcom:
|
||||
return "%s_(%s)" % (macro, m.realtype.nativeType('in').strip())
|
||||
else:
|
||||
return macro
|
||||
|
||||
def methodAsNative(m):
|
||||
scriptable = m.isScriptable() and "NS_SCRIPTABLE " or ""
|
||||
|
||||
return "%s%s %s(%s)" % (scriptable,
|
||||
methodReturnType(m, 'NS_IMETHOD'),
|
||||
methodNativeName(m),
|
||||
paramlistAsNative(m.params,
|
||||
m.realtype,
|
||||
notxpcom=m.notxpcom))
|
||||
|
||||
def paramlistAsNative(l, rettype, notxpcom, empty='void'):
|
||||
l = list(l)
|
||||
if not notxpcom and rettype.name != 'void':
|
||||
l.append(xpidl.Param(paramtype='out',
|
||||
type=None,
|
||||
name='_retval',
|
||||
attlist=[],
|
||||
location=None,
|
||||
realtype=rettype))
|
||||
|
||||
if len(l) == 0:
|
||||
return empty
|
||||
|
||||
return ", ".join([paramAsNative(p) for p in l])
|
||||
|
||||
def paramAsNative(p):
|
||||
if p.paramtype == 'in':
|
||||
typeannotate = ''
|
||||
else:
|
||||
typeannotate = ' NS_%sPARAM' % p.paramtype.upper()
|
||||
|
||||
return "%s%s%s" % (p.nativeType(),
|
||||
p.name,
|
||||
typeannotate)
|
||||
|
||||
def paramlistNames(l, rettype, notxpcom):
|
||||
names = [p.name for p in l]
|
||||
if not notxpcom and rettype.name != 'void':
|
||||
names.append('_retval')
|
||||
if len(names) == 0:
|
||||
return ''
|
||||
return ', '.join(names)
|
||||
|
||||
header = """/*
|
||||
* DO NOT EDIT. THIS FILE IS GENERATED FROM %(filename)s
|
||||
*/
|
||||
|
||||
#ifndef __gen_%(basename)s_h__
|
||||
#define __gen_%(basename)s_h__
|
||||
"""
|
||||
|
||||
include = """
|
||||
#ifndef __gen_%(basename)s_h__
|
||||
#include "%(basename)s.h"
|
||||
#endif
|
||||
"""
|
||||
|
||||
header_end = """/* For IDL files that don't want to include root IDL files. */
|
||||
#ifndef NS_NO_VTABLE
|
||||
#define NS_NO_VTABLE
|
||||
#endif
|
||||
"""
|
||||
|
||||
footer = """
|
||||
#endif /* __gen_%(basename)s_h__ */
|
||||
"""
|
||||
|
||||
forward_decl = """class %(name)s; /* forward declaration */
|
||||
|
||||
"""
|
||||
|
||||
def idl_basename(f):
|
||||
"""returns the base name of a file with the last extension stripped"""
|
||||
return os.path.basename(f).rpartition('.')[0]
|
||||
|
||||
def print_header(idl, fd, filename):
|
||||
fd.write(header % {'filename': filename,
|
||||
'basename': idl_basename(filename)})
|
||||
|
||||
foundinc = False
|
||||
for inc in idl.includes():
|
||||
if not foundinc:
|
||||
foundinc = True
|
||||
fd.write('\n')
|
||||
fd.write(include % {'basename': idl_basename(inc.filename)})
|
||||
|
||||
fd.write('\n')
|
||||
fd.write(header_end)
|
||||
|
||||
for p in idl.productions:
|
||||
if p.kind == 'include': continue
|
||||
if p.kind == 'cdata':
|
||||
fd.write(p.data)
|
||||
continue
|
||||
|
||||
if p.kind == 'forward':
|
||||
fd.write(forward_decl % {'name': p.name})
|
||||
continue
|
||||
if p.kind == 'interface':
|
||||
write_interface(p, fd)
|
||||
continue
|
||||
if p.kind == 'typedef':
|
||||
printComments(fd, p.doccomments, '')
|
||||
fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType('in'),
|
||||
p.name))
|
||||
|
||||
fd.write(footer % {'basename': idl_basename(filename)})
|
||||
|
||||
iface_header = r"""
|
||||
/* starting interface: %(name)s */
|
||||
#define %(defname)s_IID_STR "%(iid)s"
|
||||
|
||||
#define %(defname)s_IID \
|
||||
{0x%(m0)s, 0x%(m1)s, 0x%(m2)s, \
|
||||
{ %(m3joined)s }}
|
||||
|
||||
"""
|
||||
|
||||
uuid_decoder = re.compile(r"""(?P<m0>[a-f0-9]{8})-
|
||||
(?P<m1>[a-f0-9]{4})-
|
||||
(?P<m2>[a-f0-9]{4})-
|
||||
(?P<m3>[a-f0-9]{4})-
|
||||
(?P<m4>[a-f0-9]{12})$""", re.X)
|
||||
|
||||
iface_prolog = """ {
|
||||
public:
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(%(defname)s_IID)
|
||||
|
||||
"""
|
||||
|
||||
iface_epilog = """};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(%(name)s, %(defname)s_IID)
|
||||
|
||||
/* Use this macro when declaring classes that implement this interface. */
|
||||
#define NS_DECL_%(macroname)s """
|
||||
|
||||
|
||||
iface_forward = """
|
||||
|
||||
/* Use this macro to declare functions that forward the behavior of this interface to another object. */
|
||||
#define NS_FORWARD_%(macroname)s(_to) """
|
||||
|
||||
iface_forward_safe = """
|
||||
|
||||
/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */
|
||||
#define NS_FORWARD_SAFE_%(macroname)s(_to) """
|
||||
|
||||
iface_template_prolog = """
|
||||
|
||||
#if 0
|
||||
/* Use the code below as a template for the implementation class for this interface. */
|
||||
|
||||
/* Header file */
|
||||
class %(implclass)s : public %(name)s
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_%(macroname)s
|
||||
|
||||
%(implclass)s();
|
||||
|
||||
private:
|
||||
~%(implclass)s();
|
||||
|
||||
protected:
|
||||
/* additional members */
|
||||
};
|
||||
|
||||
/* Implementation file */
|
||||
NS_IMPL_ISUPPORTS1(%(implclass)s, %(name)s)
|
||||
|
||||
%(implclass)s::%(implclass)s()
|
||||
{
|
||||
/* member initializers and constructor code */
|
||||
}
|
||||
|
||||
%(implclass)s::~%(implclass)s()
|
||||
{
|
||||
/* destructor code */
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
example_tmpl = """%(returntype)s %(implclass)s::%(nativeName)s(%(paramList)s)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
"""
|
||||
|
||||
iface_template_epilog = """/* End of implementation class template. */
|
||||
#endif
|
||||
|
||||
"""
|
||||
|
||||
def write_interface(iface, fd):
|
||||
if iface.namemap is None:
|
||||
raise Exception("Interface was not resolved.")
|
||||
|
||||
def write_const_decl(c):
|
||||
printComments(fd, c.doccomments, ' ')
|
||||
|
||||
basetype = c.basetype
|
||||
value = c.getValue()
|
||||
|
||||
fd.write(" enum { %(name)s = %(value)s%(signed)s };\n\n" % {
|
||||
'name': c.name,
|
||||
'value': value,
|
||||
'signed': (not basetype.signed) and 'U' or ''})
|
||||
|
||||
def write_method_decl(m):
|
||||
printComments(fd, m.doccomments, ' ')
|
||||
|
||||
fd.write(" /* %s */\n" % m.toIDL())
|
||||
fd.write(" %s = 0;\n\n" % methodAsNative(m))
|
||||
|
||||
def write_attr_decl(a):
|
||||
printComments(fd, a.doccomments, ' ')
|
||||
|
||||
fd.write(" /* %s */\n" % a.toIDL());
|
||||
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, True))
|
||||
if not a.readonly:
|
||||
fd.write(" %s = 0;\n" % attributeAsNative(a, False))
|
||||
fd.write("\n")
|
||||
|
||||
defname = iface.name.upper()
|
||||
if iface.name[0:2] == 'ns':
|
||||
defname = 'NS_' + defname[2:]
|
||||
|
||||
names = uuid_decoder.match(iface.attributes.uuid).groupdict()
|
||||
m3str = names['m3'] + names['m4']
|
||||
names['m3joined'] = ", ".join(["0x%s" % m3str[i:i+2] for i in xrange(0, 16, 2)])
|
||||
|
||||
if iface.name[2] == 'I':
|
||||
implclass = iface.name[:2] + iface.name[3:]
|
||||
else:
|
||||
implclass = '_MYCLASS_'
|
||||
|
||||
names.update({'defname': defname,
|
||||
'macroname': iface.name.upper(),
|
||||
'name': iface.name,
|
||||
'iid': iface.attributes.uuid,
|
||||
'implclass': implclass})
|
||||
|
||||
fd.write(iface_header % names)
|
||||
|
||||
printComments(fd, iface.doccomments, '')
|
||||
|
||||
fd.write("class ")
|
||||
foundcdata = False
|
||||
for m in iface.members:
|
||||
if isinstance(m, xpidl.CDATA):
|
||||
foundcdata = True
|
||||
|
||||
if not foundcdata:
|
||||
fd.write("NS_NO_VTABLE ")
|
||||
|
||||
if iface.attributes.scriptable:
|
||||
fd.write("NS_SCRIPTABLE ")
|
||||
if iface.attributes.deprecated:
|
||||
fd.write("NS_DEPRECATED ")
|
||||
fd.write(iface.name)
|
||||
if iface.base:
|
||||
fd.write(" : public %s" % iface.base)
|
||||
fd.write(iface_prolog % names)
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.ConstMember):
|
||||
write_const_decl(member)
|
||||
elif isinstance(member, xpidl.Attribute):
|
||||
write_attr_decl(member)
|
||||
elif isinstance(member, xpidl.Method):
|
||||
write_method_decl(member)
|
||||
elif isinstance(member, xpidl.CDATA):
|
||||
fd.write(" %s" % member.data)
|
||||
else:
|
||||
raise Exception("Unexpected interface member: %s" % member)
|
||||
|
||||
fd.write(iface_epilog % names)
|
||||
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
fd.write("\\\n %s; " % attributeAsNative(member, True))
|
||||
if not member.readonly:
|
||||
fd.write("\\\n %s; " % attributeAsNative(member, False))
|
||||
elif isinstance(member, xpidl.Method):
|
||||
fd.write("\\\n %s; " % methodAsNative(member))
|
||||
if len(iface.members) == 0:
|
||||
fd.write('\\\n /* no methods! */')
|
||||
elif not member.kind in ('attribute', 'method'):
|
||||
fd.write('\\')
|
||||
|
||||
fd.write(iface_forward % names)
|
||||
|
||||
def emitTemplate(tmpl):
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
fd.write(tmpl % {'asNative': attributeAsNative(member, True),
|
||||
'nativeName': attributeNativeName(member, True),
|
||||
'paramList': attributeParamName(member)})
|
||||
if not member.readonly:
|
||||
fd.write(tmpl % {'asNative': attributeAsNative(member, False),
|
||||
'nativeName': attributeNativeName(member, False),
|
||||
'paramList': attributeParamName(member)})
|
||||
elif isinstance(member, xpidl.Method):
|
||||
fd.write(tmpl % {'asNative': methodAsNative(member),
|
||||
'nativeName': methodNativeName(member),
|
||||
'paramList': paramlistNames(member.params, member.realtype, member.notxpcom)})
|
||||
if len(iface.members) == 0:
|
||||
fd.write('\\\n /* no methods! */')
|
||||
elif not member.kind in ('attribute', 'method'):
|
||||
fd.write('\\')
|
||||
|
||||
emitTemplate("\\\n %(asNative)s { return _to %(nativeName)s(%(paramList)s); } ")
|
||||
|
||||
fd.write(iface_forward_safe % names)
|
||||
|
||||
emitTemplate("\\\n %(asNative)s { return !_to ? NS_ERROR_NULL_POINTER : _to->%(nativeName)s(%(paramList)s); } ")
|
||||
|
||||
fd.write(iface_template_prolog % names)
|
||||
|
||||
for member in iface.members:
|
||||
if isinstance(member, xpidl.ConstMember) or isinstance(member, xpidl.CDATA): continue
|
||||
fd.write("/* %s */\n" % member.toIDL())
|
||||
if isinstance(member, xpidl.Attribute):
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': 'NS_IMETHODIMP',
|
||||
'nativeName': attributeNativeName(member, True),
|
||||
'paramList': attributeParamlist(member, True)})
|
||||
if not member.readonly:
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': 'NS_IMETHODIMP',
|
||||
'nativeName': attributeNativeName(member, False),
|
||||
'paramList': attributeParamlist(member, False)})
|
||||
elif isinstance(member, xpidl.Method):
|
||||
fd.write(example_tmpl % {'implclass': implclass,
|
||||
'returntype': methodReturnType(member, 'NS_IMETHODIMP'),
|
||||
'nativeName': methodNativeName(member),
|
||||
'paramList': paramlistAsNative(member.params, member.realtype, notxpcom=member.notxpcom, empty='')})
|
||||
fd.write('\n')
|
||||
|
||||
fd.write(iface_template_epilog)
|
||||
|
||||
if __name__ == '__main__':
|
||||
from optparse import OptionParser
|
||||
o = OptionParser()
|
||||
o.add_option('-I', action='append', dest='incdirs', help="Directory to search for imported files", default=[])
|
||||
o.add_option('--cachedir', dest='cachedir', help="Directory in which to cache lex/parse tables.", default='')
|
||||
options, args = o.parse_args()
|
||||
file, = args
|
||||
|
||||
if options.cachedir != '':
|
||||
sys.path.append(options.cachedir)
|
||||
|
||||
p = xpidl.IDLParser(outputdir=options.cachedir)
|
||||
idl = p.parse(open(file).read(), filename=file)
|
||||
idl.resolve(options.incdirs, p)
|
||||
print_header(idl, sys.stdout, file)
|
1243
xpcom/idl-parser/xpidl.py
Normal file
1243
xpcom/idl-parser/xpidl.py
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user