Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLScriptElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "nsIDOMHTMLScriptElement.h"
00038 #include "nsIDOMEventReceiver.h"
00039 #include "nsGenericHTMLElement.h"
00040 #include "nsHTMLAtoms.h"
00041 #include "nsStyleConsts.h"
00042 #include "nsPresContext.h"
00043 #include "nsITextContent.h"
00044 #include "nsIDocument.h"
00045 #include "nsIScriptLoader.h"
00046 #include "nsIScriptLoaderObserver.h"
00047 #include "nsIScriptElement.h"
00048 #include "nsGUIEvent.h"
00049 #include "nsIURI.h"
00050 #include "nsNetUtil.h"
00051 
00052 #include "nsUnicharUtils.h"  // for nsCaseInsensitiveCaseComparator()
00053 #include "jsapi.h"
00054 #include "nsIScriptContext.h"
00055 #include "nsIScriptGlobalObject.h"
00056 #include "nsIXPConnect.h"
00057 #include "nsServiceManagerUtils.h"
00058 #include "nsIScriptEventHandler.h"
00059 #include "nsIDOMDocument.h"
00060 
00061 
00062 //
00063 // Helper class used to support <SCRIPT FOR=object EVENT=handler ...>
00064 // style script tags...
00065 //
00066 class nsHTMLScriptEventHandler : public nsIScriptEventHandler
00067 {
00068 public:
00069   nsHTMLScriptEventHandler(nsIDOMHTMLScriptElement *aOuter);
00070   virtual ~nsHTMLScriptEventHandler() {};
00071 
00072   // nsISupports
00073   NS_DECL_ISUPPORTS
00074 
00075   // nsIScriptEventHandler interface...
00076   NS_DECL_NSISCRIPTEVENTHANDLER
00077 
00078   // Helper method called by nsHTMLScriptElement
00079   nsresult ParseEventString(const nsAString &aValue);
00080 
00081 protected:
00082   // WEAK reference to outer object.
00083   nsIDOMHTMLScriptElement *mOuter;
00084 
00085   // Javascript argument names must be ASCII...
00086   nsCStringArray mArgNames;
00087 
00088   // The event name is kept UCS2 for 'quick comparisions'...
00089   nsString mEventName;
00090 };
00091 
00092 
00093 nsHTMLScriptEventHandler::nsHTMLScriptEventHandler(nsIDOMHTMLScriptElement *aOuter)
00094 {
00095 
00096   // Weak reference...
00097   mOuter = aOuter;
00098 }
00099 
00100 //
00101 // nsISupports Implementation
00102 //
00103 NS_IMPL_ADDREF (nsHTMLScriptEventHandler)
00104 NS_IMPL_RELEASE(nsHTMLScriptEventHandler)
00105 
00106 NS_INTERFACE_MAP_BEGIN(nsHTMLScriptEventHandler)
00107 // All interfaces are delegated to the outer object...
00108 NS_INTERFACE_MAP_END_AGGREGATED(mOuter)
00109 
00110 
00111 //
00112 // Parse the EVENT attribute into an array of argument names...
00113 //
00114 nsresult nsHTMLScriptEventHandler::ParseEventString(const nsAString &aValue)
00115 {
00116   nsAutoString eventSig(aValue);
00117   nsAutoString::const_iterator start, next, end;
00118 
00119   // Clear out the arguments array...
00120   mArgNames.Clear();
00121 
00122   // Eliminate all whitespace.
00123   eventSig.StripWhitespace();
00124 
00125   // Parse out the event name from the signature...
00126   eventSig.BeginReading(start);
00127   eventSig.EndReading(end);
00128 
00129   next = start;
00130   if (FindCharInReadable('(', next, end)) {
00131     mEventName = Substring(start, next);
00132   } else {
00133     // There is no opening parenthesis...
00134     return NS_ERROR_FAILURE;
00135   }
00136 
00137   ++next;  // skip over the '('
00138   --end;   // Move back 1 character -- hopefully to the ')'
00139   if (*end != ')') {
00140     // The arguments are not enclosed in parentheses...
00141     return NS_ERROR_FAILURE;
00142   }
00143 
00144   // Javascript expects all argument names to be ASCII.
00145   NS_LossyConvertUCS2toASCII sig(Substring(next, end));
00146 
00147   // Store each (comma separated) argument in mArgNames
00148   mArgNames.ParseString(sig.get(), ",");
00149 
00150   return NS_OK;
00151 }
00152 
00153 NS_IMETHODIMP
00154 nsHTMLScriptEventHandler::IsSameEvent(const nsAString &aObjectName,
00155                                       const nsAString &aEventName,
00156                                       PRUint32 aArgCount,
00157                                       PRBool *aResult)
00158 {
00159   *aResult = PR_FALSE;
00160 
00161   // First compare the event name.
00162   // Currently, both the case and number of arguments associated with the
00163   // event are ignored...
00164   if (aEventName.Equals(mEventName, nsCaseInsensitiveStringComparator())) {
00165     nsAutoString id;
00166 
00167     // Next compare the target object...
00168     mOuter->GetHtmlFor(id);
00169     if (aObjectName.Equals(id)) {
00170       *aResult = PR_TRUE;
00171     }
00172   }
00173 
00174   return NS_OK;
00175 }
00176 
00177 NS_IMETHODIMP
00178 nsHTMLScriptEventHandler::Invoke(nsISupports *aTargetObject,
00179                                  void *aArgs,
00180                                  PRUint32 aArgCount)
00181 {
00182   nsresult rv;
00183   nsAutoString scriptBody;
00184 
00185   // Initial sanity checking
00186   //
00187   // It's 'ok' for aArgCount to be different from mArgNames.Count().
00188   // This just means that the number of args being passed in is
00189   // different from the number it is compiled with...
00190   if (!aTargetObject || (aArgCount && !aArgs) ) {
00191     return NS_ERROR_FAILURE;
00192   }
00193 
00194   // Get the text of the script to execute...
00195   rv = mOuter->GetText(scriptBody);
00196   if (NS_FAILED(rv)) {
00197     return rv;
00198   }
00199 
00200   // Get the line number of the script (used when compiling)
00201   PRUint32 lineNumber = 0;
00202   nsCOMPtr<nsIScriptElement> sele(do_QueryInterface(mOuter));
00203   if (sele) {
00204     lineNumber = sele->GetScriptLineNumber();
00205   }
00206 
00207   // Get the script context...
00208   nsCOMPtr<nsIDOMDocument> domdoc;
00209   nsCOMPtr<nsIScriptContext> scriptContext;
00210   nsIScriptGlobalObject *sgo;
00211 
00212   mOuter->GetOwnerDocument(getter_AddRefs(domdoc));
00213 
00214   nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc));
00215   if (doc) {
00216     sgo = doc->GetScriptGlobalObject();
00217     if (sgo) {
00218       scriptContext = sgo->GetContext();
00219     }
00220   }
00221   // Fail if is no script context is available...
00222   if (!scriptContext) {
00223     return NS_ERROR_FAILURE;
00224   }
00225 
00226   // wrap the target object...
00227   JSContext *cx = (JSContext *)scriptContext->GetNativeContext();
00228   JSObject *scriptObject = nsnull;
00229 
00230   nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00231   nsContentUtils::XPConnect()->WrapNative(cx, sgo->GetGlobalJSObject(),
00232                                           aTargetObject,
00233                                           NS_GET_IID(nsISupports),
00234                                           getter_AddRefs(holder));
00235   if (holder) {
00236     holder->GetJSObject(&scriptObject);
00237   }
00238 
00239   // Fail if wrapping the native object failed...
00240   if (!scriptObject) {
00241     return NS_ERROR_FAILURE;
00242   }
00243 
00244   // Build up the array of argument names...
00245   //
00246   // Since this array is temporary (and const) the 'argument name' strings
00247   // are NOT copied.  Instead each element points into the underlying buffer
00248   // of the corresponding element in the mArgNames array...
00249   //
00250   // Remember, this is the number of arguments to compile the function with...
00251   // So, use mArgNames.Count()
00252   //
00253   const int kMaxArgsOnStack = 10;
00254 
00255   PRInt32 argc, i;
00256   const char** args;
00257   const char*  stackArgs[kMaxArgsOnStack];
00258 
00259   args = stackArgs;
00260   argc = mArgNames.Count();
00261 
00262   // If there are too many arguments then allocate the array from the heap
00263   // otherwise build it up on the stack...
00264   if (argc >= kMaxArgsOnStack) {
00265     args = new const char*[argc+1];
00266     if (!args) return NS_ERROR_OUT_OF_MEMORY;
00267   }
00268 
00269   for(i=0; i<argc; i++) {
00270     args[i] = mArgNames[i]->get();
00271   }
00272 
00273   // Null terminate for good luck ;-)
00274   args[i] = nsnull;
00275 
00276   // Compile the event handler script...
00277   void* funcObject = nsnull;
00278   NS_NAMED_LITERAL_CSTRING(funcName, "anonymous");
00279 
00280   rv = scriptContext->CompileFunction(scriptObject,
00281                                       funcName,   // method name
00282                                       argc,       // no of arguments
00283                                       args,       // argument names
00284                                       scriptBody, // script text
00285                                       nsnull,     // XXX: URL
00286                                       lineNumber, // line no (for errors)
00287                                       PR_FALSE,   // shared ?
00288                                       &funcObject);
00289   // Free the argument names array if it was heap allocated...
00290   if (args != stackArgs) {
00291     delete [] args;
00292   }
00293 
00294   // Fail if there was an error compiling the script.
00295   if (NS_FAILED(rv)) {
00296     return rv;
00297   }
00298 
00299   // Invoke the event handler script...
00300   jsval dummy;
00301   return scriptContext->CallEventHandler(scriptObject, (JSObject *)funcObject,
00302                                          aArgCount, (jsval *)aArgs, &dummy);
00303 }
00304 
00305 
00306 class nsHTMLScriptElement : public nsGenericHTMLElement,
00307                             public nsIDOMHTMLScriptElement,
00308                             public nsIScriptLoaderObserver,
00309                             public nsIScriptElement
00310 {
00311 public:
00312   nsHTMLScriptElement(nsINodeInfo *aNodeInfo);
00313   virtual ~nsHTMLScriptElement();
00314 
00315   // nsISupports
00316   NS_DECL_ISUPPORTS_INHERITED
00317 
00318   // nsIDOMNode
00319   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
00320 
00321   // nsIDOMElement
00322   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
00323 
00324   // nsIDOMHTMLElement
00325   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
00326 
00327   // nsIDOMHTMLScriptElement
00328   NS_DECL_NSIDOMHTMLSCRIPTELEMENT
00329 
00330   // nsIScriptLoaderObserver
00331   NS_DECL_NSISCRIPTLOADEROBSERVER
00332 
00333   // nsIScriptElement
00334   virtual void GetScriptType(nsAString& type);
00335   virtual already_AddRefed<nsIURI> GetScriptURI();
00336   virtual void GetScriptText(nsAString& text);
00337   virtual void GetScriptCharset(nsAString& charset); 
00338   virtual void SetScriptLineNumber(PRUint32 aLineNumber);
00339   virtual PRUint32 GetScriptLineNumber();
00340 
00341   // nsIContent
00342   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00343                    const nsAString& aValue, PRBool aNotify)
00344   {
00345     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
00346   }
00347   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00348                            nsIAtom* aPrefix, const nsAString& aValue,
00349                            PRBool aNotify);
00350 
00351   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00352                               nsIContent* aBindingParent,
00353                               PRBool aCompileEventHandlers);
00354   virtual nsresult InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00355                                  PRBool aNotify);
00356   virtual nsresult AppendChildTo(nsIContent* aKid, PRBool aNotify);
00357 
00358   virtual nsresult GetInnerHTML(nsAString& aInnerHTML);
00359   virtual nsresult SetInnerHTML(const nsAString& aInnerHTML);
00360 
00361 protected:
00362   PRBool IsOnloadEventForWindow();
00363 
00364   PRUint32 mLineNumber;
00365   PRPackedBool mIsEvaluated;
00366   PRPackedBool mEvaluating;
00367 
00368   // Pointer to the script handler helper object (OWNING reference)
00369   nsHTMLScriptEventHandler *mScriptEventHandler;
00370 
00384   void MaybeProcessScript();
00385 };
00386 
00387 
00388 NS_IMPL_NS_NEW_HTML_ELEMENT(Script)
00389 
00390 
00391 nsHTMLScriptElement::nsHTMLScriptElement(nsINodeInfo *aNodeInfo)
00392   : nsGenericHTMLElement(aNodeInfo)
00393 {
00394   mLineNumber = 0;
00395   mIsEvaluated = PR_FALSE;
00396   mEvaluating = PR_FALSE;
00397   mScriptEventHandler = nsnull;
00398 }
00399 
00400 nsHTMLScriptElement::~nsHTMLScriptElement()
00401 {
00402   NS_IF_RELEASE(mScriptEventHandler);
00403 }
00404 
00405 
00406 NS_IMPL_ADDREF_INHERITED(nsHTMLScriptElement, nsGenericElement)
00407 NS_IMPL_RELEASE_INHERITED(nsHTMLScriptElement, nsGenericElement)
00408 
00409 // QueryInterface implementation for nsHTMLScriptElement
00410 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLScriptElement, nsGenericHTMLElement)
00411   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLScriptElement)
00412   NS_INTERFACE_MAP_ENTRY(nsIScriptLoaderObserver)
00413   NS_INTERFACE_MAP_ENTRY(nsIScriptElement)
00414   if (mScriptEventHandler && aIID.Equals(NS_GET_IID(nsIScriptEventHandler)))
00415     foundInterface = NS_STATIC_CAST(nsIScriptEventHandler*,
00416                                     mScriptEventHandler);
00417   else
00418   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLScriptElement)
00419 NS_HTML_CONTENT_INTERFACE_MAP_END
00420 
00421 
00422 nsresult
00423 nsHTMLScriptElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00424                              nsIAtom* aPrefix, const nsAString& aValue,
00425                              PRBool aNotify)
00426 {
00427   nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
00428                                               aValue, aNotify);
00429   NS_ENSURE_SUCCESS(rv, rv);
00430 
00431   if (aNameSpaceID != kNameSpaceID_None) {
00432     return rv;
00433   }
00434 
00435   if (aNotify && aName == nsHTMLAtoms::src) {
00436     MaybeProcessScript();
00437   }
00438 
00439   return rv;
00440 }
00441 
00442 nsresult
00443 nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00444                                 nsIContent* aBindingParent,
00445                                 PRBool aCompileEventHandlers)
00446 {
00447   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
00448                                                  aBindingParent,
00449                                                  aCompileEventHandlers);
00450   NS_ENSURE_SUCCESS(rv, rv);
00451 
00452   if (aDocument) {
00453     MaybeProcessScript();
00454   }
00455 
00456   return rv;
00457 }
00458 
00459 nsresult
00460 nsHTMLScriptElement::InsertChildAt(nsIContent* aKid, PRUint32 aIndex,
00461                                    PRBool aNotify)
00462 {
00463   nsresult rv = nsGenericHTMLElement::InsertChildAt(aKid, aIndex, aNotify);
00464   if (NS_SUCCEEDED(rv) && aNotify) {
00465     MaybeProcessScript();
00466   }
00467 
00468   return rv;
00469 }
00470 
00471 nsresult
00472 nsHTMLScriptElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
00473 {
00474   nsresult rv = nsGenericHTMLElement::AppendChildTo(aKid, aNotify);
00475   if (NS_SUCCEEDED(rv) && aNotify) {
00476     MaybeProcessScript();
00477   }
00478 
00479   return rv;
00480 }
00481 
00482 nsresult
00483 nsHTMLScriptElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn)
00484 {
00485   *aReturn = nsnull;
00486 
00487   nsHTMLScriptElement* it = new nsHTMLScriptElement(mNodeInfo);
00488   if (!it) {
00489     return NS_ERROR_OUT_OF_MEMORY;
00490   }
00491 
00492   nsCOMPtr<nsIDOMNode> kungFuDeathGrip(it);
00493 
00494   CopyInnerTo(it, aDeep);
00495 
00496   // The clone should be marked evaluated if we are.  It should also be marked
00497   // evaluated if we're evaluating, to handle the case when this script node's
00498   // script clones the node.
00499   it->mIsEvaluated = mIsEvaluated || mEvaluating;
00500   it->mLineNumber = mLineNumber;
00501 
00502   kungFuDeathGrip.swap(*aReturn);
00503 
00504   return NS_OK;
00505 }
00506 
00507 NS_IMETHODIMP
00508 nsHTMLScriptElement::GetText(nsAString& aValue)
00509 {
00510   GetContentsAsText(aValue);
00511   return NS_OK;
00512 }
00513 
00514 NS_IMETHODIMP
00515 nsHTMLScriptElement::SetText(const nsAString& aValue)
00516 {
00517   return ReplaceContentsWithText(aValue, PR_TRUE);
00518 }
00519 
00520 
00521 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Charset, charset)
00522 NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Defer, defer)
00523 NS_IMPL_URI_ATTR(nsHTMLScriptElement, Src, src)
00524 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Type, type)
00525 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, HtmlFor, _for)
00526 NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Event, _event)
00527 
00528 nsresult
00529 nsHTMLScriptElement::GetInnerHTML(nsAString& aInnerHTML)
00530 {
00531   GetContentsAsText(aInnerHTML);
00532   return NS_OK;
00533 }
00534 
00535 nsresult
00536 nsHTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML)
00537 {
00538   return ReplaceContentsWithText(aInnerHTML, PR_TRUE);
00539 }
00540 
00541 // variation of this code in nsSVGScriptElement - check if changes
00542 // need to be transfered when modifying
00543 
00544 /* void scriptAvailable (in nsresult aResult, in nsIScriptElement aElement , in nsIURI aURI, in PRInt32 aLineNo, in PRUint32 aScriptLength, [size_is (aScriptLength)] in wstring aScript); */
00545 NS_IMETHODIMP
00546 nsHTMLScriptElement::ScriptAvailable(nsresult aResult,
00547                                      nsIScriptElement *aElement,
00548                                      PRBool aIsInline,
00549                                      PRBool aWasPending,
00550                                      nsIURI *aURI,
00551                                      PRInt32 aLineNo,
00552                                      const nsAString& aScript)
00553 {
00554   if (!aIsInline && NS_FAILED(aResult)) {
00555     nsEventStatus status = nsEventStatus_eIgnore;
00556     nsScriptErrorEvent event(PR_TRUE, NS_SCRIPT_ERROR);
00557 
00558     event.lineNr = aLineNo;
00559 
00560     NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
00561     event.errorMsg = errorString.get();
00562 
00563     nsCAutoString spec;
00564     aURI->GetSpec(spec);
00565 
00566     NS_ConvertUTF8toUCS2 fileName(spec);
00567     event.fileName = fileName.get();
00568 
00569     nsCOMPtr<nsPresContext> presContext = GetPresContext();
00570     HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
00571   }
00572 
00573   return NS_OK;
00574 }
00575 
00576 // variation of this code in nsSVGScriptElement - check if changes
00577 // need to be transfered when modifying
00578 
00579 /* void scriptEvaluated (in nsresult aResult, in nsIScriptElement aElement); */
00580 NS_IMETHODIMP
00581 nsHTMLScriptElement::ScriptEvaluated(nsresult aResult,
00582                                      nsIScriptElement *aElement,
00583                                      PRBool aIsInline,
00584                                      PRBool aWasPending)
00585 {
00586   nsresult rv = NS_OK;
00587   if (!aIsInline) {
00588     nsEventStatus status = nsEventStatus_eIgnore;
00589     nsEvent event(PR_TRUE,
00590                   NS_SUCCEEDED(aResult) ? NS_SCRIPT_LOAD : NS_SCRIPT_ERROR);
00591     nsCOMPtr<nsPresContext> presContext = GetPresContext();
00592     rv = HandleDOMEvent(presContext, &event, nsnull, NS_EVENT_FLAG_INIT,
00593                         &status);
00594   }
00595 
00596   return rv;
00597 }
00598 
00599 void
00600 nsHTMLScriptElement::GetScriptType(nsAString& type)
00601 {
00602   GetType(type);
00603 }
00604 
00605 // variation of this code in nsSVGScriptElement - check if changes
00606 // need to be transfered when modifying
00607 
00608 already_AddRefed<nsIURI>
00609 nsHTMLScriptElement::GetScriptURI()
00610 {
00611   nsIURI *uri = nsnull;
00612   nsAutoString src;
00613   GetSrc(src);
00614   if (!src.IsEmpty())
00615     NS_NewURI(&uri, src);
00616   return uri;
00617 }
00618 
00619 void
00620 nsHTMLScriptElement::GetScriptText(nsAString& text)
00621 {
00622   GetText(text);
00623 }
00624 
00625 void
00626 nsHTMLScriptElement::GetScriptCharset(nsAString& charset)
00627 {
00628   GetCharset(charset);
00629 }
00630 
00631 void 
00632 nsHTMLScriptElement::SetScriptLineNumber(PRUint32 aLineNumber)
00633 {
00634   mLineNumber = aLineNumber;
00635 }
00636 
00637 PRUint32
00638 nsHTMLScriptElement::GetScriptLineNumber()
00639 {
00640   return mLineNumber;
00641 }
00642 
00643 // variation of this code in nsSVGScriptElement - check if changes
00644 // need to be transfered when modifying
00645 
00646 void
00647 nsHTMLScriptElement::MaybeProcessScript()
00648 {
00649   if (mIsEvaluated || mEvaluating || !IsInDoc()) {
00650     return;
00651   }
00652 
00653   // We'll always call this to make sure that
00654   // ScriptAvailable/ScriptEvaluated gets called. See bug 153600
00655   nsresult rv = NS_OK;
00656   nsCOMPtr<nsIScriptLoader> loader = GetOwnerDoc()->GetScriptLoader();
00657   if (loader) {
00658     mEvaluating = PR_TRUE;
00659     rv = loader->ProcessScriptElement(this, this);
00660     mEvaluating = PR_FALSE;
00661   }
00662 
00663   if (rv == NS_CONTENT_SCRIPT_IS_EVENTHANDLER) {
00664 
00665     // If the script has NOT been executed yet then create a script
00666     // event handler if necessary...
00667     if (!mIsEvaluated && !mScriptEventHandler) {
00668       // Set mIsEvaluated, this element will be handled by the
00669       // nsIScriptEventManager
00670       mIsEvaluated = PR_TRUE;
00671 
00672       mScriptEventHandler = new nsHTMLScriptEventHandler(this);
00673       if (!mScriptEventHandler) {
00674         return;
00675       }
00676 
00677       NS_ADDREF(mScriptEventHandler);
00678 
00679       // The script-loader will make sure that the script is not evaluated
00680       // right away.
00681     }
00682 
00683     if (mScriptEventHandler) {
00684       nsAutoString event_val;
00685       GetAttr(kNameSpaceID_None, nsHTMLAtoms::_event, event_val);
00686       mScriptEventHandler->ParseEventString(event_val);
00687     }
00688   }
00689 
00690   // But we'll only set mIsEvaluated if we did really load or evaluate
00691   // something
00692   if (HasAttr(kNameSpaceID_None, nsHTMLAtoms::src) ||
00693       mAttrsAndChildren.ChildCount()) {
00694     mIsEvaluated = PR_TRUE;
00695   }
00696 }