Make XBL methods and properties report useful line numbers and urls so that the

JS errors/warnings in the JS console point to the right place.  Bug 127567,
r=bryner, sr=alecf


git-svn-id: svn://10.0.0.236/trunk@144079 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bzbarsky%mit.edu
2003-06-24 01:20:40 +00:00
parent 7de2ca34d1
commit 63ed4e4cd2
15 changed files with 206 additions and 78 deletions

View File

@@ -328,7 +328,8 @@ PRBool
nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRInt32 aNameSpaceID,
nsIAtom* aTagName)
nsIAtom* aTagName,
PRUint32 aLineNumber)
{
PRBool ret = PR_TRUE;
if (aNameSpaceID == kNameSpaceID_XBL) {
@@ -362,7 +363,7 @@ nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts,
}
else if (aTagName == nsXBLAtoms::handler) {
mSecondaryState = eXBL_InHandler;
ConstructHandler(aAtts);
ConstructHandler(aAtts, aLineNumber);
ret = PR_FALSE;
}
else if (aTagName == nsXBLAtoms::resources) {
@@ -387,6 +388,7 @@ nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts,
nsnull, nsnull, nsnull, nsnull,
nsnull, nsnull);
newHandler->SetEventName(nsXBLAtoms::constructor);
newHandler->SetLineNumber(aLineNumber);
mBinding->SetConstructor(newHandler);
}
else if (aTagName == nsXBLAtoms::destructor) {
@@ -396,28 +398,42 @@ nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts,
nsnull, nsnull, nsnull, nsnull,
nsnull, nsnull);
newHandler->SetEventName(nsXBLAtoms::destructor);
newHandler->SetLineNumber(aLineNumber);
mBinding->SetDestructor(newHandler);
}
else if (aTagName == nsXBLAtoms::field) {
mSecondaryState = eXBL_InField;
ConstructField(aAtts);
ConstructField(aAtts, aLineNumber);
}
else if (aTagName == nsXBLAtoms::property) {
mSecondaryState = eXBL_InProperty;
ConstructProperty(aAtts);
}
else if (aTagName == nsXBLAtoms::getter)
else if (aTagName == nsXBLAtoms::getter) {
if (mSecondaryState == eXBL_InProperty && mProperty) {
mProperty->SetGetterLineNumber(aLineNumber);
}
mSecondaryState = eXBL_InGetter;
else if (aTagName == nsXBLAtoms::setter)
}
else if (aTagName == nsXBLAtoms::setter) {
if (mSecondaryState == eXBL_InProperty && mProperty) {
mProperty->SetSetterLineNumber(aLineNumber);
}
mSecondaryState = eXBL_InSetter;
}
else if (aTagName == nsXBLAtoms::method) {
mSecondaryState = eXBL_InMethod;
ConstructMethod(aAtts);
}
else if (aTagName == nsXBLAtoms::parameter)
ConstructParameter(aAtts);
else if (aTagName == nsXBLAtoms::body)
else if (aTagName == nsXBLAtoms::body) {
if (mSecondaryState == eXBL_InMethod && mMethod) {
// stash away the line number
mMethod->SetLineNumber(aLineNumber);
}
mSecondaryState = eXBL_InBody;
}
ret = PR_FALSE; // Ignore everything we encounter inside an <implementation> block.
}
@@ -443,7 +459,7 @@ nsXBLContentSink::ConstructBinding()
void
nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts)
nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts, PRUint32 aLineNumber)
{
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
@@ -507,6 +523,8 @@ nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts)
clickcount, preventdefault);
if (newHandler) {
newHandler->SetLineNumber(aLineNumber);
// Add this handler to our chain of handlers.
if (mHandler)
mHandler->SetNextHandler(newHandler); // Already have a chain. Just append to the end.
@@ -579,7 +597,7 @@ nsXBLContentSink::ConstructImplementation(const PRUnichar **aAtts)
}
void
nsXBLContentSink::ConstructField(const PRUnichar **aAtts)
nsXBLContentSink::ConstructField(const PRUnichar **aAtts, PRUint32 aLineNumber)
{
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
@@ -607,6 +625,8 @@ nsXBLContentSink::ConstructField(const PRUnichar **aAtts)
// parameters.
mField = new nsXBLProtoImplField(name, readonly);
if (mField) {
mField->SetLineNumber(aLineNumber);
// Add this member to our chain.
if (mImplMember)
mImplMember->SetNext(mField); // Already have a chain. Just append to the end.

View File

@@ -104,7 +104,8 @@ protected:
PRBool OnOpenContainer(const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRInt32 aNameSpaceID,
nsIAtom* aTagName);
nsIAtom* aTagName,
PRUint32 aLineNumber);
nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
@@ -121,13 +122,13 @@ protected:
// Our own helpers for constructing XBL prototype objects.
void ConstructBinding();
void ConstructHandler(const PRUnichar **aAtts);
void ConstructHandler(const PRUnichar **aAtts, PRUint32 aLineNumber);
void ConstructResource(const PRUnichar **aAtts, nsIAtom* aResourceType);
void ConstructImplementation(const PRUnichar **aAtts);
void ConstructProperty(const PRUnichar **aAtts);
void ConstructMethod(const PRUnichar **aAtts);
void ConstructParameter(const PRUnichar **aAtts);
void ConstructField(const PRUnichar **aAtts);
void ConstructField(const PRUnichar **aAtts, PRUint32 aLineNumber);
// nsXMLContentSink overrides

View File

@@ -108,6 +108,7 @@ nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext, nsIContent* aBoun
// compile the literal string
jsval result = nsnull;
PRBool undefined;
// XXX Need a URI here!
aContext->EvaluateStringWithValue(nsDependentString(mFieldText,
mFieldTextLength),
scriptObject,

View File

@@ -55,6 +55,10 @@ public:
virtual void Destroy(PRBool aIsCompiled);
void AppendFieldText(const nsAString& aText);
void SetLineNumber(PRUint32 aLineNumber) {
// XXXbz fields need to have a URI in InstallMember (see XXX
// comment there) before line number reporting will be useful.
}
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
void* aScriptObject, void* aTargetClassObject);

View File

@@ -51,6 +51,50 @@
class nsIScriptContext;
MOZ_DECL_CTOR_COUNTER(nsXBLTextWithLineNumber)
struct nsXBLTextWithLineNumber
{
PRUnichar* mText;
PRUint32 mLineNumber;
nsXBLTextWithLineNumber() :
mText(nsnull),
mLineNumber(0)
{
MOZ_COUNT_CTOR(nsXBLTextWithLineNumber);
}
~nsXBLTextWithLineNumber() {
MOZ_COUNT_DTOR(nsXBLTextWithLineNumber);
if (mText) {
nsMemory::Free(mText);
}
}
void AppendText(const nsAString& aText) {
if (mText) {
PRUnichar* temp = mText;
mText = ToNewUnicode(nsDependentString(temp) + aText);
nsMemory::Free(temp);
} else {
mText = ToNewUnicode(aText);
}
}
PRUnichar* GetText() {
return mText;
}
void SetLineNumber(PRUint32 aLineNumber) {
mLineNumber = aLineNumber;
}
PRUint32 GetLineNumber() {
return mLineNumber;
}
};
class nsXBLProtoImplMember
{
public:

View File

@@ -99,9 +99,9 @@ RemoveJSGCRoot(void* aScriptObjectRef)
MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplMethod);
nsXBLProtoImplMethod::nsXBLProtoImplMethod(const PRUnichar* aName)
:nsXBLProtoImplMember(aName),
mUncompiledMethod(nsnull)
nsXBLProtoImplMethod::nsXBLProtoImplMethod(const PRUnichar* aName) :
nsXBLProtoImplMember(aName),
mUncompiledMethod(nsnull)
{
MOZ_COUNT_CTOR(nsXBLProtoImplMethod);
}
@@ -149,6 +149,18 @@ nsXBLProtoImplMethod::AddParameter(const nsAString& aText)
mUncompiledMethod->AddParameter(aText);
}
void
nsXBLProtoImplMethod::SetLineNumber(PRUint32 aLineNumber)
{
if (!mUncompiledMethod) {
mUncompiledMethod = new nsXBLUncompiledMethod();
if (!mUncompiledMethod)
return;
}
mUncompiledMethod->SetLineNumber(aLineNumber);
}
nsresult
nsXBLProtoImplMethod::InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
void* aScriptObject, void* aTargetClassObject)
@@ -204,14 +216,15 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
// Now that we have a body and args, compile the function
// and then define it.
nsDependentString body(mUncompiledMethod->mBodyText);
nsDependentString body(mUncompiledMethod->mBodyText.GetText());
if (!body.IsEmpty()) {
nsCAutoString cname; cname.AssignWithConversion(mName);
NS_ConvertUCS2toUTF8 cname(mName);
nsCAutoString functionUri(aClassStr);
functionUri += ".";
functionUri += cname;
functionUri += "()";
PRInt32 hash = functionUri.RFindChar('#');
if (hash != kNotFound) {
functionUri.Truncate(hash);
}
JSObject* methodObject = nsnull;
aContext->CompileFunction(aClassObject,
cname,
@@ -219,7 +232,7 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
(const char**)args,
body,
functionUri.get(),
0,
mUncompiledMethod->mBodyText.GetLineNumber(),
PR_FALSE,
(void **) &methodObject);

View File

@@ -71,18 +71,18 @@ MOZ_DECL_CTOR_COUNTER(nsXBLUncompiledMethod)
struct nsXBLUncompiledMethod {
nsXBLParameter* mParameters;
nsXBLParameter* mLastParameter;
PRUnichar* mBodyText;
nsXBLTextWithLineNumber mBodyText;
nsXBLUncompiledMethod() {
nsXBLUncompiledMethod() :
mParameters(nsnull),
mLastParameter(nsnull),
mBodyText()
{
MOZ_COUNT_CTOR(nsXBLUncompiledMethod);
mBodyText = nsnull;
mParameters = nsnull;
mLastParameter = nsnull;
}
~nsXBLUncompiledMethod() {
MOZ_COUNT_DTOR(nsXBLUncompiledMethod);
nsMemory::Free(mBodyText);
delete mParameters;
}
@@ -94,13 +94,7 @@ struct nsXBLUncompiledMethod {
}
void AppendBodyText(const nsAString& aText) {
if (mBodyText) {
PRUnichar* temp = mBodyText;
mBodyText = ToNewUnicode(nsDependentString(temp) + aText);
nsMemory::Free(temp);
}
else
mBodyText = ToNewUnicode(aText);
mBodyText.AppendText(aText);
}
void AddParameter(const nsAString& aText) {
@@ -113,6 +107,10 @@ struct nsXBLUncompiledMethod {
mLastParameter->mNext = param;
mLastParameter = param;
}
void SetLineNumber(PRUint32 aLineNumber) {
mBodyText.SetLineNumber(aLineNumber);
}
};
class nsXBLProtoImplMethod: public nsXBLProtoImplMember
@@ -125,6 +123,8 @@ public:
void AppendBodyText(const nsAString& aBody);
void AddParameter(const nsAString& aName);
void SetLineNumber(PRUint32 aLineNumber);
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
void* aScriptObject, void* aTargetClassObject);
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject);

View File

@@ -102,14 +102,14 @@ MOZ_DECL_CTOR_COUNTER(nsXBLProtoImplProperty);
nsXBLProtoImplProperty::nsXBLProtoImplProperty(const PRUnichar* aName,
const PRUnichar* aGetter,
const PRUnichar* aSetter,
const PRUnichar* aReadOnly)
:nsXBLProtoImplMember(aName),
mGetterText(nsnull),
mSetterText(nsnull)
const PRUnichar* aReadOnly) :
nsXBLProtoImplMember(aName),
mGetterText(nsnull),
mSetterText(nsnull),
mJSAttributes(JSPROP_ENUMERATE)
{
MOZ_COUNT_CTOR(nsXBLProtoImplProperty);
mJSAttributes = JSPROP_ENUMERATE;
if (aReadOnly) {
nsAutoString readOnly; readOnly.Assign(*aReadOnly);
if (readOnly.EqualsIgnoreCase("true"))
@@ -138,8 +138,8 @@ nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
mJSGetterObject = mJSSetterObject = nsnull;
}
else {
nsMemory::Free(mGetterText);
nsMemory::Free(mSetterText);
delete mGetterText;
delete mSetterText;
mGetterText = mSetterText = nsnull;
}
}
@@ -147,25 +147,47 @@ nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
void
nsXBLProtoImplProperty::AppendGetterText(const nsAString& aText)
{
if (mGetterText) {
PRUnichar* temp = mGetterText;
mGetterText = ToNewUnicode(nsDependentString(temp) + aText);
nsMemory::Free(temp);
if (!mGetterText) {
mGetterText = new nsXBLTextWithLineNumber();
if (!mGetterText)
return;
}
else
mGetterText = ToNewUnicode(aText);
mGetterText->AppendText(aText);
}
void
nsXBLProtoImplProperty::AppendSetterText(const nsAString& aText)
{
if (mSetterText) {
PRUnichar* temp = mSetterText;
mSetterText = ToNewUnicode(nsDependentString(temp) + aText);
nsMemory::Free(temp);
if (!mSetterText) {
mSetterText = new nsXBLTextWithLineNumber();
if (!mSetterText)
return;
}
else
mSetterText = ToNewUnicode(aText);
mSetterText->AppendText(aText);
}
void
nsXBLProtoImplProperty::SetGetterLineNumber(PRUint32 aLineNumber) {
if (!mGetterText) {
mGetterText = new nsXBLTextWithLineNumber();
if (!mGetterText)
return;
}
mGetterText->SetLineNumber(aLineNumber);
}
void
nsXBLProtoImplProperty::SetSetterLineNumber(PRUint32 aLineNumber) {
if (!mSetterText) {
mSetterText = new nsXBLTextWithLineNumber();
if (!mSetterText)
return;
}
mSetterText->SetLineNumber(aLineNumber);
}
const char* gPropertyArgs[] = { "val" };
@@ -215,25 +237,29 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
nsresult rv = NS_OK;
// Do we have a getter?
nsAutoString getter(mGetterText);
nsAutoString getter(mGetterText ? mGetterText->GetText() : nsnull);
PRUint32 lineNo = mGetterText ? mGetterText->GetLineNumber() : 0;
// Make sure we free mGetterText here before calling
// CompileFunction() since that'll overwrite mGetterText
nsMemory::Free(mGetterText);
delete mGetterText;
mGetterText = nsnull;
nsCAutoString functionUri;
if (!getter.IsEmpty() && aClassObject) {
functionUri = aClassStr + NS_LITERAL_CSTRING(".");
AppendUTF16toUTF8(mName, functionUri);
functionUri += NS_LITERAL_CSTRING(" (getter)");
functionUri = aClassStr;
PRInt32 hash = functionUri.RFindChar('#');
if (hash != kNotFound) {
functionUri.Truncate(hash);
}
rv = aContext->CompileFunction(aClassObject,
nsCAutoString("onget"),
NS_LITERAL_CSTRING("get_") +
NS_ConvertUCS2toUTF8(mName),
0,
nsnull,
getter,
functionUri.get(),
0,
lineNo,
PR_FALSE,
(void **) &mJSGetterObject);
if (mJSGetterObject && NS_SUCCEEDED(rv)) {
@@ -254,24 +280,28 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
nsresult rvG=rv;
// Do we have a setter?
nsAutoString setter(mSetterText);
nsAutoString setter(mSetterText ? mSetterText->GetText() : nsnull);
lineNo = mSetterText ? mSetterText->GetLineNumber() : 0;
// Make sure we free mSetterText here before calling
// CompileFunction() since that'll overwrite mSetterText
nsMemory::Free(mSetterText);
delete mSetterText;
mSetterText = nsnull;
if (!setter.IsEmpty() && aClassObject) {
functionUri = aClassStr + NS_LITERAL_CSTRING(".");
AppendUTF16toUTF8(mName, functionUri);
functionUri += NS_LITERAL_CSTRING(" (setter)");
functionUri = aClassStr;
PRInt32 hash = functionUri.RFindChar('#');
if (hash != kNotFound) {
functionUri.Truncate(hash);
}
rv = aContext->CompileFunction(aClassObject,
nsCAutoString("onset"),
NS_LITERAL_CSTRING("set_") +
NS_ConvertUCS2toUTF8(mName),
1,
gPropertyArgs,
setter,
functionUri.get(),
0,
lineNo,
PR_FALSE,
(void **) &mJSSetterObject);
if (mJSSetterObject && NS_SUCCEEDED(rv)) {

View File

@@ -61,23 +61,29 @@ public:
void AppendGetterText(const nsAString& aGetter);
void AppendSetterText(const nsAString& aSetter);
void SetGetterLineNumber(PRUint32 aLineNumber);
void SetSetterLineNumber(PRUint32 aLineNumber);
virtual nsresult InstallMember(nsIScriptContext* aContext, nsIContent* aBoundElement,
void* aScriptObject, void* aTargetClassObject);
virtual nsresult CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr, void* aClassObject);
protected:
union {
PRUnichar* mGetterText; // The raw text for the getter (prior to compilation).
JSObject * mJSGetterObject; // The JS object for the getter (after compilation)
// The raw text for the getter (prior to compilation).
nsXBLTextWithLineNumber* mGetterText;
// The JS object for the getter (after compilation)
JSObject * mJSGetterObject;
};
union {
PRUnichar* mSetterText; // The raw text for the setter (prior to compilation).
JSObject * mJSSetterObject; // The JS object for the setter (after compilation)
// The raw text for the setter (prior to compilation).
nsXBLTextWithLineNumber* mSetterText;
// The JS object for the setter (after compilation)
JSObject * mJSSetterObject;
};
uintN mJSAttributes; // A flag for all our JS properties (getter/setter/readonly/shared/enum)
PRBool mCompiled; // Whether or not we are compiled.
};
#endif // nsXBLProtoImplProperty_h__

View File

@@ -83,6 +83,13 @@ public:
void AppendHandlerText(const nsAString& aText);
void SetLineNumber(PRUint32 aLineNumber) {
// XXXbz JS event handlers do not have line numbers associated to
// them... see the XXXbe comment in nsJSContext::CompileEventHandler
// We can get line numbers here easily; getting the filename/URI
// of the script will be much harder...
}
PRUint8 GetPhase() { return mPhase; }
PRUint8 GetType() { return mType; }

View File

@@ -1726,7 +1726,7 @@ nsXMLContentSink::HandleStartElement(const PRUnichar *aName,
PRInt32 nameSpaceID = GetNameSpaceId(nameSpacePrefix);
if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, tagAtom))
if (!OnOpenContainer(aAtts, aAttsCount, nameSpaceID, tagAtom, aLineNumber))
return NS_OK;
nsCOMPtr<nsINodeInfo> nodeInfo;

View File

@@ -125,7 +125,8 @@ protected:
virtual PRBool OnOpenContainer(const PRUnichar **aAtts,
PRUint32 aAttsCount,
PRInt32 aNameSpaceID,
nsIAtom* aTagName) { return PR_TRUE; }
nsIAtom* aTagName,
PRUint32 aLineNumber) { return PR_TRUE; }
virtual nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
nsIContent** aResult, PRBool* aAppendContent);

View File

@@ -213,7 +213,7 @@ public:
void* aHandler) = 0;
NS_IMETHOD CompileFunction(void* aTarget,
const nsCString& aName,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,

View File

@@ -1021,7 +1021,7 @@ nsJSContext::CompileEventHandler(void *aTarget, nsIAtom *aName,
NS_IMETHODIMP
nsJSContext::CompileFunction(void* aTarget,
const nsCString& aName,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,
@@ -1048,7 +1048,8 @@ nsJSContext::CompileFunction(void* aTarget,
JSObject *target = (JSObject*)aTarget;
JSFunction* fun =
::JS_CompileUCFunctionForPrincipals(mContext, target, jsprin,
aName.get(), aArgCount, aArgArray,
PromiseFlatCString(aName).get(),
aArgCount, aArgArray,
(jschar*)(const PRUnichar*)PromiseFlatString(aBody).get(),
aBody.Length(),
aURL, aLineNo);

View File

@@ -99,7 +99,7 @@ public:
nsIAtom *aName,
void *aHandler);
NS_IMETHOD CompileFunction(void* aTarget,
const nsCString& aName,
const nsACString& aName,
PRUint32 aArgCount,
const char** aArgArray,
const nsAString& aBody,