michael@0: /* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsISupports.idl" michael@0: michael@0: %{ C++ michael@0: #include "jsdebug.h" michael@0: #include "nsAString.h" michael@0: %} michael@0: michael@0: [ptr] native JSDContext(JSDContext); michael@0: [ptr] native JSDObject(JSDObject); michael@0: [ptr] native JSDProperty(JSDProperty); michael@0: [ptr] native JSDScript(JSDScript); michael@0: [ptr] native JSDStackFrameInfo(JSDStackFrameInfo); michael@0: [ptr] native JSDThreadState(JSDThreadState); michael@0: [ptr] native JSDValue(JSDValue); michael@0: [ptr] native JSRuntime(JSRuntime); michael@0: [ptr] native JSContext(JSContext); michael@0: [ptr] native JSCompartment(JSCompartment); michael@0: michael@0: /* interfaces we declare in this file */ michael@0: interface jsdIDebuggerService; michael@0: interface jsdIFilter; michael@0: interface jsdINestCallback; michael@0: interface jsdIFilterEnumerator; michael@0: interface jsdIContextEnumerator; michael@0: interface jsdIScriptEnumerator; michael@0: interface jsdIScriptHook; michael@0: interface jsdIErrorHook; michael@0: interface jsdIExecutionHook; michael@0: interface jsdICallHook; michael@0: interface jsdIEphemeral; michael@0: interface jsdIContext; michael@0: interface jsdIStackFrame; michael@0: interface jsdIScript; michael@0: interface jsdIValue; michael@0: interface jsdIObject; michael@0: interface jsdIProperty; michael@0: interface jsdIActivationCallback; michael@0: michael@0: /** michael@0: * Debugger service. It is not a good idea to have more than one active client michael@0: * of the debugger service. michael@0: * michael@0: * Note that all the APIs in this file are deprecated. All consumers of michael@0: * these interfaces should switch to using the new Debugger API, documented michael@0: * here: https://wiki.mozilla.org/Debugger michael@0: */ michael@0: [scriptable, uuid(39609752-2d73-4019-a324-a374dee16d3c)] michael@0: interface jsdIDebuggerService : nsISupports michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: michael@0: /** michael@0: * Called when an error or warning occurs. michael@0: */ michael@0: attribute jsdIErrorHook errorHook; michael@0: /** michael@0: * Called when a jsdIScript is created or destroyed. michael@0: */ michael@0: attribute jsdIScriptHook scriptHook; michael@0: /** michael@0: * Called when the engine encounters a breakpoint. michael@0: */ michael@0: attribute jsdIExecutionHook breakpointHook; michael@0: /** michael@0: * Called when the engine encounters the debugger keyword. michael@0: */ michael@0: attribute jsdIExecutionHook debuggerHook; michael@0: /** michael@0: * Called when the errorHook returns false. michael@0: */ michael@0: attribute jsdIExecutionHook debugHook; michael@0: /** michael@0: * Called before the next PC is executed. michael@0: */ michael@0: attribute jsdIExecutionHook interruptHook; michael@0: /** michael@0: * Called when an exception is thrown (even if it will be caught.) michael@0: */ michael@0: attribute jsdIExecutionHook throwHook; michael@0: /** michael@0: * Called before and after a toplevel script is evaluated. michael@0: */ michael@0: attribute jsdICallHook topLevelHook; michael@0: /** michael@0: * Called before and after a function is called. michael@0: */ michael@0: attribute jsdICallHook functionHook; michael@0: michael@0: /** michael@0: * Link native frames in call stacks. michael@0: */ michael@0: const unsigned long ENABLE_NATIVE_FRAMES = 0x01; michael@0: /** michael@0: * Normally, if a script has a 0 in JSD_SCRIPT_PROFILE_BIT it is included in michael@0: * profile data, otherwise it is not profiled. Setting the michael@0: * PROFILE_WHEN_SET flag reverses this convention. michael@0: */ michael@0: const unsigned long PROFILE_WHEN_SET = 0x02; michael@0: /** michael@0: * Normally, when the script in the top frame of a thread state has a 1 in michael@0: * JSD_SCRIPT_DEBUG_BIT, the execution hook is ignored. Setting the michael@0: * DEBUG_WHEN_SET flag reverses this convention. michael@0: */ michael@0: const unsigned long DEBUG_WHEN_SET = 0x04; michael@0: /** michael@0: * When this flag is set the internal call hook will collect profile data. michael@0: */ michael@0: const unsigned long COLLECT_PROFILE_DATA = 0x08; michael@0: /** michael@0: * When this flag is set, stack frames that are disabled for debugging michael@0: * will not appear in the call stack chain. michael@0: */ michael@0: const unsigned long HIDE_DISABLED_FRAMES = 0x10; michael@0: /** michael@0: * When this flag is set, the debugger will only check the michael@0: * JSD_SCRIPT_DEBUG_BIT on the top (most recent) stack frame. This michael@0: * makes it possible to stop in an enabled frame which was called from michael@0: * a stack that contains a disabled frame. michael@0: * michael@0: * When this flag is *not* set, any stack that contains a disabled frame michael@0: * will not be debugged (the execution hook will not be invoked.) michael@0: * michael@0: * This only applies when the reason for calling the hook would have michael@0: * been TYPE_INTERRUPTED or TYPE_THROW. TYPE_BREAKPOINT, michael@0: * TYPE_DEBUG_REQUESTED, and TYPE_DEBUGGER_KEYWORD always stop, regardless michael@0: * of this setting, as long as the top frame is not disabled. michael@0: * michael@0: * If HIDE_DISABLED_FRAMES is set, this is effectively set as well. michael@0: */ michael@0: const unsigned long MASK_TOP_FRAME_ONLY = 0x20; michael@0: /** michael@0: * This flag has been retired, do not re-use. It previously provided a hook michael@0: * for object allocation. michael@0: */ michael@0: const unsigned long DISABLE_OBJECT_TRACE_RETIRED = 0x40; michael@0: michael@0: /** michael@0: * Debugger service flags. michael@0: */ michael@0: attribute unsigned long flags; michael@0: michael@0: /** michael@0: * Major version number of implementation. michael@0: */ michael@0: readonly attribute unsigned long implementationMajor; michael@0: /** michael@0: * Minor version number of implementation. michael@0: */ michael@0: readonly attribute unsigned long implementationMinor; michael@0: /** michael@0: * Free form AUTF8String identifier for implementation. michael@0: */ michael@0: readonly attribute AUTF8String implementationString; michael@0: michael@0: /** michael@0: * |true| if the debugger service has been turned on. This does not michael@0: * necessarily mean another app is actively using the service, as the michael@0: * autostart pref may have turned the service on. michael@0: */ michael@0: readonly attribute boolean isOn; michael@0: michael@0: michael@0: /** michael@0: * Synchronous activation of the debugger is no longer supported, michael@0: * and will throw an exception. michael@0: */ michael@0: void on(); michael@0: michael@0: /** michael@0: * Turn on the debugger. This function should only be called from michael@0: * JavaScript code. The debugger will be enabled on the runtime the call is michael@0: * made on, as determined by nsIXPCNativeCallContext. michael@0: * michael@0: * The debugger will be activated asynchronously, because there can be no michael@0: * JS on the stack when code is to be re-compiled for debug mode. michael@0: */ michael@0: void asyncOn(in jsdIActivationCallback callback); michael@0: michael@0: /** michael@0: * Called by nsIXPConnect after it's had a chance to recompile for michael@0: * debug mode. michael@0: */ michael@0: [noscript] void activateDebugger(in JSRuntime rt); michael@0: michael@0: /** michael@0: * Called by nsIXPConnect to deactivate debugger on setup failure. michael@0: */ michael@0: [noscript] void deactivateDebugger(); michael@0: michael@0: /** michael@0: * Recompile all active scripts in the runtime for debugMode. michael@0: */ michael@0: [noscript] void recompileForDebugMode(in JSContext cx, in JSCompartment comp, in boolean mode); michael@0: michael@0: /** michael@0: * Turn the debugger off. This will invalidate all of your jsdIEphemeral michael@0: * derived objects, and clear all of your breakpoints. michael@0: */ michael@0: void off (); michael@0: michael@0: /** michael@0: * Peek at the current pause depth of the debugger. michael@0: * michael@0: * @return depth Number of pause() calls still waiting to be unPause()d. michael@0: */ michael@0: readonly attribute unsigned long pauseDepth; michael@0: /** michael@0: * Temporarily disable the debugger. Hooks will not be called while the michael@0: * debugger is paused. Multiple calls to pause will increase the "pause michael@0: * depth", and equal number of unPause calles must be made to resume michael@0: * normal debugging. michael@0: * michael@0: * @return depth Number of times pause has been called since the debugger michael@0: * has been unpaused. michael@0: */ michael@0: unsigned long pause(); michael@0: /** michael@0: * Undo a pause. Once this is called, the debugger won't start michael@0: * getting execution callbacks until the stack is fully unwound so michael@0: * that no JS scripts are live. There is no way to query whether michael@0: * there are such scripts left to unwind at a given point in time. michael@0: * michael@0: * @return depth The number of remaining pending pause calls. michael@0: */ michael@0: unsigned long unPause(); michael@0: michael@0: /** michael@0: * Force the engine to perform garbage collection. michael@0: */ michael@0: void GC(); michael@0: michael@0: /** michael@0: * Clear profile data for all scripts. michael@0: */ michael@0: void clearProfileData(); michael@0: michael@0: /** michael@0: * Adds an execution hook filter. These filters are consulted each time one michael@0: * of the jsdIExecutionHooks is about to be called. Filters are matched in michael@0: * a first in, first compared fashion. The first filter to match determines michael@0: * whether or not the hook is called. Use swapFilter to reorder existing michael@0: * filters, and removeFilter to remove them. michael@0: * michael@0: * If |filter| is already present this method throws NS_ERROR_INVALID_ARG. michael@0: * michael@0: * @param filter Object representing the filter to add. michael@0: * @param after Insert |filter| after this one. Pass null to insert at michael@0: * the beginning. michael@0: */ michael@0: void insertFilter(in jsdIFilter filter, in jsdIFilter after); michael@0: /** michael@0: * Same as insertFilter, except always add to the end of the list. michael@0: */ michael@0: void appendFilter(in jsdIFilter filter); michael@0: /** michael@0: * Remove a filter. michael@0: * michael@0: * If |filter| is not present this method throws NS_ERROR_INVALID_ARG. michael@0: * michael@0: * @param filter Object representing the filter to remove. Must be the exact michael@0: * object passed to addFilter, not just a new object with the same michael@0: * properties. michael@0: */ michael@0: void removeFilter(in jsdIFilter filter); michael@0: /** michael@0: * Swap position of two filters. michael@0: * michael@0: * If |filter_a| is not present, this method throws NS_ERROR_INVALID_ARG. michael@0: * If |filter_b| is not present, filter_a is replaced by filter_b. michael@0: * If |filter_a| == |filter_b|, then filter is refreshed. michael@0: */ michael@0: void swapFilters(in jsdIFilter filter_a, in jsdIFilter filter_b); michael@0: /** michael@0: * Enumerate registered filters. This routine refreshes each filter before michael@0: * passing them on to the enumeration function. Calling this with a null michael@0: * |enumerator| is equivalent to jsdIService::refreshFilters. michael@0: * michael@0: * @param enumerator jsdIFilterEnumerator instance to be called back for the michael@0: * enumeration. michael@0: */ michael@0: void enumerateFilters(in jsdIFilterEnumerator enumerator); michael@0: /** michael@0: * Force the debugger to resync its internal filter cache with the michael@0: * actual values in the jsdIFilter objects. To refresh a single filter michael@0: * use jsdIService::swapFilters. This method is equivalent to michael@0: * jsdIService::enumerateFilters with a null enumerator. michael@0: */ michael@0: void refreshFilters(); michael@0: /** michael@0: * Clear the list of filters. michael@0: */ michael@0: void clearFilters(); michael@0: michael@0: /** michael@0: * Enumerate all known contexts. michael@0: */ michael@0: void enumerateContexts(in jsdIContextEnumerator enumerator); michael@0: michael@0: /** michael@0: * Enumerate all scripts the debugger knows about. Any scripts created michael@0: * before you turned the debugger on, or after turning the debugger off michael@0: * will not be available unless the autostart perf is set. michael@0: * michael@0: * @param enumerator jsdIScriptEnumerator instance to be called back for michael@0: * the enumeration. michael@0: */ michael@0: void enumerateScripts(in jsdIScriptEnumerator enumerator); michael@0: /** michael@0: * Clear all breakpoints in all scripts. michael@0: */ michael@0: void clearAllBreakpoints(); michael@0: michael@0: /** michael@0: * When called from JavaScript, this method returns the jsdIValue wrapper michael@0: * for the given value. If a wrapper does not exist one will be created. michael@0: * When called from another language this method returns an xpconnect michael@0: * defined error code. michael@0: */ michael@0: jsdIValue wrapValue(in jsval value); michael@0: michael@0: /* XXX these two routines are candidates for refactoring. The only problem michael@0: * is that it is not clear where and how they should land. michael@0: */ michael@0: michael@0: /** michael@0: * Push a new network queue, and enter a new UI event loop. michael@0: * @param callback jsdINestCallback instance to be called back after the michael@0: * network queue has been pushed, but before the michael@0: * UI loop starts. michael@0: * @return depth returns the current number of times the event loop has been michael@0: * nested. your code can use it for sanity checks. michael@0: */ michael@0: unsigned long enterNestedEventLoop(in jsdINestCallback callback); michael@0: /** michael@0: * Exit the current nested event loop after the current iteration completes, michael@0: * and pop the network event queue. michael@0: * michael@0: * @return depth returns the current number of times the event loop has been michael@0: * nested. your code can use it for sanity checks. michael@0: */ michael@0: unsigned long exitNestedEventLoop(); michael@0: michael@0: /** michael@0: * Output dump of JS heap. michael@0: * michael@0: * @param fileName Filename to dump the heap into. michael@0: */ michael@0: void dumpHeap(in AUTF8String fileName); michael@0: michael@0: /** michael@0: * Suppress console warnings about using JSD, which is a deprecated API. michael@0: * michael@0: * This applies only to the next call to asyncOn; any subsequent calls michael@0: * will elicit the warning, unless you call 'acknowledgeDeprecation' michael@0: * before each of them, too. This arrangement ensures that one add-on's michael@0: * acknowledgement doesn't suppress warnings for other add-ons. michael@0: */ michael@0: void acknowledgeDeprecation(); michael@0: }; michael@0: michael@0: /* callback interfaces */ michael@0: michael@0: /** michael@0: * Object representing a pattern of global object and/or url the debugger should michael@0: * ignore. The debugger service itself will not modify properties of these michael@0: * objects. michael@0: */ michael@0: [scriptable, uuid(9ae587cd-b78c-47f0-a612-4b3a211a6a71)] michael@0: interface jsdIFilter : nsISupports michael@0: { michael@0: /** michael@0: * These two bytes of the flags attribute are reserved for interpretation michael@0: * by the jsdService implementation. You can do what you like with the michael@0: * remaining flags. michael@0: */ michael@0: const unsigned long FLAG_RESERVED_MASK = 0xFF; michael@0: /** michael@0: * Filters without this flag set are ignored. michael@0: */ michael@0: const unsigned long FLAG_ENABLED = 0x01; michael@0: /** michael@0: * Filters with this flag set are "pass" filters, they allow matching hooks michael@0: * to continue. Filters without this flag block matching hooks. michael@0: */ michael@0: const unsigned long FLAG_PASS = 0x02; michael@0: michael@0: /** michael@0: * FLAG_* values from above, OR'd together. michael@0: */ michael@0: attribute unsigned long flags; michael@0: michael@0: /** michael@0: * String representing the url pattern to be filtered. Supports limited michael@0: * glob matching, at the beginning and end of the pattern only. For example, michael@0: * "chrome://venkman*" filters all urls that start with chrome/venkman, michael@0: * "*.cgi" filters all cgi's, and "http://myserver/utils.js" filters only michael@0: * the utils.js file on "myserver". A null urlPattern matches all urls. michael@0: * michael@0: * The jsdIService caches this value internally, to if it changes you must michael@0: * swap the filter with itself using jsdIService::swapFilters. michael@0: */ michael@0: attribute AUTF8String urlPattern; michael@0: michael@0: /** michael@0: * Line number for the start of this filter. Line numbers are one based. michael@0: * Assigning a 0 to this attribute will tell the debugger to ignore the michael@0: * entire file. michael@0: */ michael@0: attribute unsigned long startLine; michael@0: michael@0: /** michael@0: * Line number for the end of this filter. Line numbers are one based. michael@0: * Assigning a 0 to this attribute will tell the debugger to ignore from michael@0: * |startLine| to the end of the file. michael@0: */ michael@0: attribute unsigned long endLine; michael@0: }; michael@0: michael@0: /** michael@0: * Notify client code that debugMode has been activated. michael@0: */ michael@0: [scriptable, function, uuid(6da7f5fb-3a84-4abe-9e23-8b2045960732)] michael@0: interface jsdIActivationCallback : nsISupports michael@0: { michael@0: void onDebuggerActivated(); michael@0: }; michael@0: michael@0: /** michael@0: * Pass an instance of one of these to jsdIDebuggerService::enterNestedEventLoop. michael@0: */ michael@0: [scriptable, function, uuid(88bea60f-9b5d-4b39-b08b-1c3a278782c6)] michael@0: interface jsdINestCallback : nsISupports michael@0: { michael@0: /** michael@0: * This method will be called after pre-nesting work has completed, such michael@0: * as pushing the js context and network event queue, but before the new michael@0: * event loop starts. michael@0: */ michael@0: void onNest(); michael@0: }; michael@0: michael@0: /** michael@0: * Pass an instance of one of these to jsdIDebuggerService::enumerateFilters. michael@0: */ michael@0: [scriptable, function, uuid(e391ba85-9379-4762-b387-558e38db730f)] michael@0: interface jsdIFilterEnumerator : nsISupports michael@0: { michael@0: /** michael@0: * The enumerateFilter method will be called once for every filter the michael@0: * debugger knows about. michael@0: */ michael@0: void enumerateFilter(in jsdIFilter filter); michael@0: }; michael@0: michael@0: /** michael@0: * Pass an instance of one of these to jsdIDebuggerService::enumerateScripts. michael@0: */ michael@0: [scriptable, function, uuid(4eef60c2-9bbc-48fa-b196-646a832c6c81)] michael@0: interface jsdIScriptEnumerator : nsISupports michael@0: { michael@0: /** michael@0: * The enumerateScript method will be called once for every script the michael@0: * debugger knows about. michael@0: */ michael@0: void enumerateScript(in jsdIScript script); michael@0: }; michael@0: michael@0: /** michael@0: * Pass an instance of one of these to jsdIDebuggerService::enumerateContexts. michael@0: */ michael@0: [scriptable, function, uuid(57d18286-550c-4ca9-ac33-56f12ebba91e)] michael@0: interface jsdIContextEnumerator : nsISupports michael@0: { michael@0: /** michael@0: * The enumerateContext method will be called once for every context michael@0: * currently in use. michael@0: */ michael@0: void enumerateContext(in jsdIContext executionContext); michael@0: }; michael@0: michael@0: /** michael@0: * Set jsdIDebuggerService::scriptHook to an instance of one of these. michael@0: */ michael@0: [scriptable, uuid(d030d1a2-a58a-4f19-b9e3-96da4e2cdd09)] michael@0: interface jsdIScriptHook : nsISupports michael@0: { michael@0: /** michael@0: * Called when scripts are created. michael@0: */ michael@0: void onScriptCreated(in jsdIScript script); michael@0: /** michael@0: * Called when the JavaScript engine destroys a script. The jsdIScript michael@0: * object passed in will already be invalidated. michael@0: */ michael@0: void onScriptDestroyed(in jsdIScript script); michael@0: }; michael@0: michael@0: /** michael@0: * Hook instances of this interface up to the michael@0: * jsdIDebuggerService::functionHook and toplevelHook properties. michael@0: */ michael@0: [scriptable, function, uuid(3eff1314-7ae3-4cf8-833b-c33c24a55633)] michael@0: interface jsdICallHook : nsISupports michael@0: { michael@0: /** michael@0: * TYPE_* values must be kept in sync with the JSD_HOOK_* #defines michael@0: * in jsdebug.h. michael@0: */ michael@0: michael@0: /** michael@0: * Toplevel script is starting. michael@0: */ michael@0: const unsigned long TYPE_TOPLEVEL_START = 0; michael@0: /** michael@0: * Toplevel script has completed. michael@0: */ michael@0: const unsigned long TYPE_TOPLEVEL_END = 1; michael@0: /** michael@0: * Function is being called. michael@0: */ michael@0: const unsigned long TYPE_FUNCTION_CALL = 2; michael@0: /** michael@0: * Function is returning. michael@0: */ michael@0: const unsigned long TYPE_FUNCTION_RETURN = 3; michael@0: michael@0: /** michael@0: * Called before the JavaScript engine executes a top level script or calls michael@0: * a function. michael@0: */ michael@0: void onCall(in jsdIStackFrame frame, in unsigned long type); michael@0: }; michael@0: michael@0: [scriptable, function, uuid(e6b45eee-d974-4d85-9d9e-f5a67218deb4)] michael@0: interface jsdIErrorHook : nsISupports michael@0: { michael@0: /** michael@0: * REPORT_* values must be kept in sync with JSREPORT_* #defines in michael@0: * jsapi.h michael@0: */ michael@0: michael@0: /** michael@0: * Report is an error. michael@0: */ michael@0: const unsigned long REPORT_ERROR = 0x00; michael@0: /** michael@0: * Report is only a warning. michael@0: */ michael@0: const unsigned long REPORT_WARNING = 0x01; michael@0: /** michael@0: * Report represents an uncaught exception. michael@0: */ michael@0: const unsigned long REPORT_EXCEPTION = 0x02; michael@0: /** michael@0: * Report is due to strict mode. michael@0: */ michael@0: const unsigned long REPORT_STRICT = 0x04; michael@0: michael@0: /** michael@0: * Called when the JavaScript engine encounters an error. Return |true| michael@0: * to pass the error along, |false| to invoke the debugHook. michael@0: */ michael@0: boolean onError(in AUTF8String message, in AUTF8String fileName, michael@0: in unsigned long line, in unsigned long pos, michael@0: in unsigned long flags, in unsigned long errnum, michael@0: in jsdIValue exc); michael@0: }; michael@0: michael@0: /** michael@0: * Hook instances of this interface up to the michael@0: * jsdIDebuggerService::breakpointHook, debuggerHook, errorHook, interruptHook, michael@0: * and throwHook properties. michael@0: */ michael@0: [scriptable, function, uuid(3a722496-9d78-4f0a-a797-293d9e8cb8d2)] michael@0: interface jsdIExecutionHook : nsISupports michael@0: { michael@0: /** michael@0: * TYPE_* values must be kept in sync with JSD_HOOK_* #defines in jsdebug.h. michael@0: */ michael@0: michael@0: /** michael@0: * Execution stopped because we're in single step mode. michael@0: */ michael@0: const unsigned long TYPE_INTERRUPTED = 0; michael@0: /** michael@0: * Execution stopped by a trap instruction (i.e. breakoint.) michael@0: */ michael@0: const unsigned long TYPE_BREAKPOINT = 1; michael@0: /** michael@0: * Error handler returned an "invoke debugger" value. michael@0: */ michael@0: const unsigned long TYPE_DEBUG_REQUESTED = 2; michael@0: /** michael@0: * Debugger keyword encountered. michael@0: */ michael@0: const unsigned long TYPE_DEBUGGER_KEYWORD = 3; michael@0: /** michael@0: * Exception was thrown. michael@0: */ michael@0: const unsigned long TYPE_THROW = 4; michael@0: michael@0: /** michael@0: * RETURN_* values must be kept in sync with JSD_HOOK_RETURN_* #defines in michael@0: * jsdebug.h. michael@0: */ michael@0: michael@0: /** michael@0: * Indicates unrecoverable error processing the hook. This will cause michael@0: * the script being executed to be aborted without raising a JavaScript michael@0: * exception. michael@0: */ michael@0: const unsigned long RETURN_HOOK_ERROR = 0; michael@0: /** michael@0: * Continue processing normally. This is the "do nothing special" return michael@0: * value for all hook types *except* TYPE_THROW. Returning RETURN_CONTINUE michael@0: * from TYPE_THROW cause the exception to be ignored. Return michael@0: * RETURN_CONTINUE_THROW to continue exception processing from TYPE_THROW michael@0: * hooks. michael@0: */ michael@0: const unsigned long RETURN_CONTINUE = 1; michael@0: /** michael@0: * Same effect as RETURN_HOOK_ERROR. michael@0: */ michael@0: const unsigned long RETURN_ABORT = 2; michael@0: /** michael@0: * Return the value of the |val| parameter. michael@0: */ michael@0: const unsigned long RETURN_RET_WITH_VAL = 3; michael@0: /** michael@0: * Throw the value of the |val| parameter. michael@0: */ michael@0: const unsigned long RETURN_THROW_WITH_VAL = 4; michael@0: /** michael@0: * Continue the current throw. michael@0: */ michael@0: const unsigned long RETURN_CONTINUE_THROW = 5; michael@0: michael@0: /** michael@0: * @param frame A jsdIStackFrame object representing the bottom stack frame. michael@0: * @param type One of the jsdIExecutionHook::TYPE_ constants. michael@0: * @param val in - Current exception (if any) when this method is called. michael@0: * out - If you return RETURN_THROW_WITH_VAL, value to be michael@0: * thrown. michael@0: * If you return RETURN_RET_WITH_VAL, value to return. michael@0: * All other return values, not significant. michael@0: * @retval One of the jsdIExecutionHook::RETURN_* constants. michael@0: */ michael@0: unsigned long onExecute(in jsdIStackFrame frame, michael@0: in unsigned long type, inout jsdIValue val); michael@0: }; michael@0: michael@0: /** michael@0: * Objects which inherit this interface may go away, with (jsdIScript) or michael@0: * without (all others) notification. These objects are generally wrappers michael@0: * around JSD structures that go away when you call jsdService::Off(). michael@0: */ michael@0: [scriptable, uuid(46f1e23e-1dd2-11b2-9ceb-8285f2e95e69)] michael@0: interface jsdIEphemeral : nsISupports michael@0: { michael@0: /** michael@0: * |true| if this object is still valid. If not, many or all of the methods michael@0: * and/or properties of the inheritor may no longer be callable. michael@0: */ michael@0: readonly attribute boolean isValid; michael@0: /** michael@0: * Mark this instance as invalid. michael@0: */ michael@0: [noscript] void invalidate(); michael@0: }; michael@0: michael@0: /* handle objects */ michael@0: michael@0: /** michael@0: * Context object. Only context's which are also nsISupports objects can be michael@0: * reflected by this interface. michael@0: */ michael@0: [scriptable, uuid(3e5c934d-6863-4d81-96f5-76a3b962fc2b)] michael@0: interface jsdIContext : jsdIEphemeral michael@0: { michael@0: /* Internal use only. */ michael@0: [noscript] readonly attribute JSContext JSContext; michael@0: michael@0: /** michael@0: * OPT_* values must be kept in sync with JSOPTION_* #defines in jsapi.h. michael@0: */ michael@0: michael@0: /** michael@0: * Strict mode is on. michael@0: */ michael@0: const long OPT_STRICT = 0x01; michael@0: /** michael@0: * Warnings reported as errors. michael@0: */ michael@0: const long OPT_WERR = 0x02; michael@0: /** michael@0: * Makes eval() use the last object on its 'obj' param's scope chain as the michael@0: * ECMA 'variables object'. michael@0: */ michael@0: const long OPT_VAROBJFIX = 0x04; michael@0: /** michael@0: * Private data for this object is an nsISupports object. Attempting to michael@0: * alter this bit will result in an NS_ERROR_ILLEGAL_VALUE. michael@0: */ michael@0: const long OPT_ISUPPORTS = 0x08; michael@0: /** michael@0: * OPT_* values above, OR'd together. michael@0: */ michael@0: attribute unsigned long options; michael@0: michael@0: /** michael@0: * Unique tag among all valid jsdIContext objects, useful as a hash key. michael@0: */ michael@0: readonly attribute unsigned long tag; michael@0: michael@0: /** michael@0: * Private data for this context, if it is an nsISupports, |null| otherwise. michael@0: */ michael@0: readonly attribute nsISupports privateData; michael@0: michael@0: /** michael@0: * Retrieve the underlying context wrapped by this jsdIContext. michael@0: */ michael@0: readonly attribute nsISupports wrappedContext; michael@0: michael@0: /** michael@0: * Top of the scope chain for this context. michael@0: */ michael@0: readonly attribute jsdIValue globalObject; michael@0: michael@0: /** michael@0: * |true| if this context should be allowed to run scripts, |false| michael@0: * otherwise. This attribute is only valid for contexts which implement michael@0: * nsIScriptContext. Setting or getting this attribute on any other michael@0: * context will throw a NS_ERROR_NO_INTERFACE exception. michael@0: */ michael@0: attribute boolean scriptsEnabled; michael@0: }; michael@0: michael@0: /** michael@0: * Stack frame objects. These are only valid inside the jsdIExecutionHook which michael@0: * gave it to you. After you return from that handler the bottom frame, and any michael@0: * frame you found attached through it, are invalidated via the jsdIEphemeral michael@0: * interface. Once a jsdIStackFrame has been invalidated all method and michael@0: * property accesses will throw a NS_ERROR_NOT_AVAILABLE exception. michael@0: */ michael@0: [scriptable, uuid(7c95422c-7579-4a6f-8ef7-e5b391552ee5)] michael@0: interface jsdIStackFrame : jsdIEphemeral michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDThreadState JSDThreadState; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDStackFrameInfo JSDStackFrameInfo; michael@0: michael@0: /** michael@0: * True if stack frame represents a frame created as a result of a debugger michael@0: * evaluation. michael@0: */ michael@0: readonly attribute boolean isDebugger; michael@0: /** michael@0: * True if stack frame is constructing a new object. michael@0: */ michael@0: readonly attribute boolean isConstructing; michael@0: michael@0: /** michael@0: * Link to the caller's stack frame. michael@0: */ michael@0: readonly attribute jsdIStackFrame callingFrame; michael@0: /** michael@0: * Executon context. michael@0: */ michael@0: readonly attribute jsdIContext executionContext; michael@0: /** michael@0: * Function name executing in this stack frame. michael@0: */ michael@0: readonly attribute AUTF8String functionName; michael@0: /** michael@0: * Script running in this stack frame, null for native frames. michael@0: */ michael@0: readonly attribute jsdIScript script; michael@0: /** michael@0: * Current program counter in this stack frame. michael@0: */ michael@0: readonly attribute unsigned long pc; michael@0: /** michael@0: * Current line number (using the script's pc to line map.) michael@0: */ michael@0: readonly attribute unsigned long line; michael@0: /** michael@0: * Function object running in this stack frame. michael@0: */ michael@0: readonly attribute jsdIValue callee; michael@0: /** michael@0: * Top object in the scope chain. michael@0: */ michael@0: readonly attribute jsdIValue scope; michael@0: /** michael@0: * |this| object for this stack frame. michael@0: */ michael@0: readonly attribute jsdIValue thisValue; michael@0: /** michael@0: * Evaluate arbitrary JavaScript in this stack frame. michael@0: * @param bytes Script to be evaluated. michael@0: * @param fileName Filename to compile this script under. This is the michael@0: * filename you'll see in error messages, etc. michael@0: * @param line Starting line number for this script. One based. michael@0: * @retval Result of evaluating the script. michael@0: */ michael@0: boolean eval(in AString bytes, in AUTF8String fileName, michael@0: in unsigned long line, out jsdIValue result); michael@0: michael@0: }; michael@0: michael@0: /** michael@0: * Script object. In JavaScript engine terms, there's a single script for each michael@0: * function, and one for the top level script. michael@0: */ michael@0: [scriptable, uuid(8ce9b2a2-cc33-48a8-9f47-8696186ed9a5)] michael@0: interface jsdIScript : jsdIEphemeral michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDScript JSDScript; michael@0: michael@0: /** michael@0: * Last version set on this context. michael@0: * Scripts typically select this with the "language" attribute. michael@0: * See the VERSION_* consts on jsdIDebuggerService. michael@0: */ michael@0: readonly attribute long version; michael@0: michael@0: /** michael@0: * Tag value guaranteed unique among jsdIScript objects. Useful as a michael@0: * hash key in script. michael@0: */ michael@0: readonly attribute unsigned long tag; michael@0: michael@0: /** michael@0: * FLAG_* values need to be kept in sync with JSD_SCRIPT_* #defines in michael@0: * jsdebug.h. michael@0: */ michael@0: michael@0: /** michael@0: * Determines whether or not to collect profile information for this michael@0: * script. The context flag FLAG_PROFILE_WHEN_SET decides the logic. michael@0: */ michael@0: const unsigned long FLAG_PROFILE = 0x01; michael@0: /** michael@0: * Determines whether or not to ignore breakpoints, etc. in this script. michael@0: * The context flag JSD_DEBUG_WHEN_SET decides the logic. michael@0: */ michael@0: const unsigned long FLAG_DEBUG = 0x02; michael@0: /** michael@0: * Determines whether to invoke the onScriptDestroy callback for this michael@0: * script. The default is for this to be true if the onScriptCreated michael@0: * callback was invoked for this script. michael@0: */ michael@0: const unsigned long FLAG_CALL_DESTROY_HOOK = 0x04; michael@0: michael@0: /** michael@0: * FLAG_* attributes from above, OR'd together. michael@0: */ michael@0: attribute unsigned long flags; michael@0: michael@0: /** michael@0: * Filename given for this script when it was compiled. michael@0: * This data is copied from the underlying structure when the jsdIScript michael@0: * instance is created and is therefore available even after the script is michael@0: * invalidated. michael@0: */ michael@0: readonly attribute AUTF8String fileName; michael@0: /** michael@0: * Function name for this script. "anonymous" for unnamed functions (or michael@0: * a function actually named anonymous), empty for top level scripts. michael@0: * This data is copied from the underlying structure when the jsdIScript michael@0: * instance is created and is therefore available even after the script is michael@0: * invalidated. michael@0: */ michael@0: readonly attribute AUTF8String functionName; michael@0: /** michael@0: * The names of the arguments for this function; empty if this is michael@0: * not a function. michael@0: */ michael@0: void getParameterNames([optional] out unsigned long count, michael@0: [array, size_is(count), retval] out wstring paramNames); michael@0: /** michael@0: * Fetch the function object as a jsdIValue. michael@0: */ michael@0: readonly attribute jsdIValue functionObject; michael@0: /** michael@0: * Source code for this script, without function declaration. michael@0: */ michael@0: readonly attribute AString functionSource; michael@0: /** michael@0: * Line number in source file containing the first line of this script. michael@0: * This data is copied from the underlying structure when the jsdIScript michael@0: * instance is created and is therefore available even after the script is michael@0: * invalidated. michael@0: */ michael@0: readonly attribute unsigned long baseLineNumber; michael@0: /** michael@0: * Total number of lines in this script. michael@0: * This data is copied from the underlying structure when the jsdIScript michael@0: * instance is created and is therefore available even after the script is michael@0: * invalidated. michael@0: */ michael@0: readonly attribute unsigned long lineExtent; michael@0: michael@0: /** michael@0: * Number of times this script has been called. michael@0: */ michael@0: readonly attribute unsigned long callCount; michael@0: /** michael@0: * Number of times this script called itself, directly or indirectly. michael@0: */ michael@0: readonly attribute unsigned long maxRecurseDepth; michael@0: /** michael@0: * Shortest execution time recorded, in milliseconds. michael@0: */ michael@0: readonly attribute double minExecutionTime; michael@0: /** michael@0: * Longest execution time recorded, in milliseconds. michael@0: */ michael@0: readonly attribute double maxExecutionTime; michael@0: /** michael@0: * Total time spent in this function, in milliseconds. michael@0: */ michael@0: readonly attribute double totalExecutionTime; michael@0: /** michael@0: * Shortest execution time recorded, in milliseconds, excluding time spent michael@0: * in other called code. michael@0: */ michael@0: readonly attribute double minOwnExecutionTime; michael@0: /** michael@0: * Longest execution time recorded, in milliseconds, excluding time spent michael@0: * in other called code. michael@0: */ michael@0: readonly attribute double maxOwnExecutionTime; michael@0: /** michael@0: * Total time spent in this function, in milliseconds, excluding time spent michael@0: * in other called code. michael@0: */ michael@0: readonly attribute double totalOwnExecutionTime; michael@0: michael@0: /** michael@0: * Clear profile data for this script. michael@0: */ michael@0: void clearProfileData(); michael@0: michael@0: const unsigned long PCMAP_SOURCETEXT = 1; /* map to actual source text */ michael@0: const unsigned long PCMAP_PRETTYPRINT = 2; /* map to pretty printed source */ michael@0: michael@0: /** michael@0: * Get the closest line number to a given PC. michael@0: * The |pcmap| argument specifies which pc to source line map to use. michael@0: */ michael@0: unsigned long pcToLine(in unsigned long pc, in unsigned long pcmap); michael@0: /** michael@0: * Get the first PC associated with a line. michael@0: * The |pcmap| argument specifies which pc to source line map to use. michael@0: */ michael@0: unsigned long lineToPc(in unsigned long line, in unsigned long pcmap); michael@0: /** michael@0: * Determine is a particular line is executable, like checking that michael@0: * lineToPc == pcToLine, except in one call. michael@0: * The |pcmap| argument specifies which pc to source line map to use. michael@0: */ michael@0: boolean isLineExecutable(in unsigned long line, in unsigned long pcmap); michael@0: michael@0: /** michael@0: * Return a list of all executable lines in a script. michael@0: * |pcmap| specifies which pc to source line map to use. michael@0: * |startLine| and |maxLines| may be used to retrieve a chunk at a time. michael@0: */ michael@0: void getExecutableLines(in unsigned long pcmap, michael@0: in unsigned long startLine, in unsigned long maxLines, michael@0: [optional] out unsigned long count, michael@0: [array, size_is(count), retval] out unsigned long executableLines); michael@0: michael@0: /** michael@0: * Set a breakpoint at a PC in this script. michael@0: */ michael@0: void setBreakpoint(in unsigned long pc); michael@0: /** michael@0: * Clear a breakpoint at a PC in this script. michael@0: */ michael@0: void clearBreakpoint(in unsigned long pc); michael@0: /** michael@0: * Clear all breakpoints set in this script. michael@0: */ michael@0: void clearAllBreakpoints(); michael@0: /** michael@0: * Call interrupt hook at least once per source line michael@0: */ michael@0: void enableSingleStepInterrupts(in boolean mode); michael@0: }; michael@0: michael@0: /** michael@0: * Value objects. Represents typeless JavaScript values (jsval in SpiderMonkey michael@0: * terminology.) These are valid until the debugger is turned off. Holding a michael@0: * jsdIValue adds a root for the underlying JavaScript value, so don't keep it michael@0: * if you don't need to. michael@0: */ michael@0: [scriptable, uuid(1cd3535b-4ddb-4202-9053-e0ec88f5c82b)] michael@0: interface jsdIValue : jsdIEphemeral michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDValue JSDValue; michael@0: michael@0: /** michael@0: * |false| unless the value is a function declared in script. michael@0: */ michael@0: readonly attribute boolean isNative; michael@0: /** michael@0: * |true| if the value represents a number, either double or integer. michael@0: * |false| for all other values, including numbers assigned as strings michael@0: * (eg. x = "1";) michael@0: */ michael@0: readonly attribute boolean isNumber; michael@0: /** michael@0: * |true| if the value represents a JavaScript primitive number or AUTF8String michael@0: */ michael@0: readonly attribute boolean isPrimitive; michael@0: michael@0: /** Value is either |true| or |false|. */ michael@0: const unsigned long TYPE_BOOLEAN = 0; michael@0: /** Value is a primitive number that is too large to fit in an integer. */ michael@0: const unsigned long TYPE_DOUBLE = 1; michael@0: /** Value is a primitive number that fits into an integer. */ michael@0: const unsigned long TYPE_INT = 2; michael@0: /** Value is a function. */ michael@0: const unsigned long TYPE_FUNCTION = 3; michael@0: /** Value is |null|. */ michael@0: const unsigned long TYPE_NULL = 4; michael@0: /** Value is an object. */ michael@0: const unsigned long TYPE_OBJECT = 5; michael@0: /** Value is a primitive AUTF8String. */ michael@0: const unsigned long TYPE_STRING = 6; michael@0: /** Value is void. */ michael@0: const unsigned long TYPE_VOID = 7; michael@0: michael@0: /** michael@0: * One of the TYPE_* values above. michael@0: */ michael@0: readonly attribute unsigned long jsType; michael@0: /** michael@0: * Prototype value if this value represents an object, null if the value is michael@0: * not an object or the object has no prototype. michael@0: */ michael@0: readonly attribute jsdIValue jsPrototype; michael@0: /** michael@0: * Parent value if this value represents an object, null if the value is not michael@0: * an object or the object has no parent. michael@0: */ michael@0: readonly attribute jsdIValue jsParent; michael@0: /** michael@0: * Class name if this value represents an object. Empty AUTF8String if the value michael@0: * is not an object. michael@0: */ michael@0: readonly attribute AUTF8String jsClassName; michael@0: /** michael@0: * Constructor name if this value represents an object. Empty AUTF8String if the michael@0: * value is not an object. michael@0: */ michael@0: readonly attribute jsdIValue jsConstructor; michael@0: /** michael@0: * Function name if this value represents a function. Empty AUTF8String if the michael@0: * value is not a function. michael@0: */ michael@0: readonly attribute AUTF8String jsFunctionName; michael@0: michael@0: /** michael@0: * Value if interpreted as a boolean. Converts if necessary. michael@0: */ michael@0: readonly attribute boolean booleanValue; michael@0: /** michael@0: * Value if interpreted as a double. Converts if necessary. michael@0: */ michael@0: readonly attribute double doubleValue; michael@0: /** michael@0: * Value if interpreted as an integer. Converts if necessary. michael@0: */ michael@0: readonly attribute long intValue; michael@0: /** michael@0: * Value if interpreted as an object. michael@0: */ michael@0: readonly attribute jsdIObject objectValue; michael@0: /** michael@0: * Value if interpreted as a AUTF8String. Converts if necessary. michael@0: */ michael@0: readonly attribute AUTF8String stringValue; michael@0: michael@0: /** michael@0: * Number of properties. 0 if the value is not an object, or the value is michael@0: * an object but has no properties. michael@0: */ michael@0: readonly attribute long propertyCount; michael@0: michael@0: /** michael@0: * Retrieves all properties if this value represents an object. If this michael@0: * value is not an object a 0 element array is returned. michael@0: * @param propArray Array of jsdIProperty values for this value. michael@0: * @param length Size of array. michael@0: */ michael@0: void getProperties([array, size_is(length)] out jsdIProperty propArray, michael@0: out unsigned long length); michael@0: /** michael@0: * Retrieves a single property from the value. Only valid if the value michael@0: * represents an object. michael@0: * @param name Name of the property to retrieve. michael@0: * @retval jsdIProperty for the requested property name or null if no michael@0: * property exists for the requested name. michael@0: */ michael@0: jsdIProperty getProperty(in AUTF8String name); michael@0: michael@0: /** michael@0: * jsdIValues are wrappers around JavaScript engine structures. Much of the michael@0: * data is copied instead of shared. The refresh method is used to resync michael@0: * the jsdIValue with the underlying structure. michael@0: */ michael@0: void refresh(); michael@0: michael@0: /** michael@0: * When called from JavaScript, this method returns the JavaScript value michael@0: * wrapped by this jsdIValue. The calling script is free to use the result michael@0: * as it would any other JavaScript value. michael@0: * When called from another language this method returns an xpconnect michael@0: * defined error code. michael@0: */ michael@0: [implicit_jscontext] jsval getWrappedValue(); michael@0: michael@0: /** michael@0: * If this is a function value, return its associated jsdIScript. michael@0: * Otherwise, return null. michael@0: */ michael@0: readonly attribute jsdIScript script; michael@0: }; michael@0: michael@0: /** michael@0: * Properties specific to values which are also objects. michael@0: * XXX We don't add roots for these yet, so make sure you hold on to the michael@0: * jsdIValue from whence your jsdIObject instance came for at least as long as michael@0: * you hold the jsdIObject. michael@0: * XXX Maybe the jsClassName, jsConstructorName, and property related attribute/ michael@0: * functions from jsdIValue should move to this interface. We could inherit from michael@0: * jsdIValue or use interface flattening or something. michael@0: */ michael@0: [scriptable, uuid(87d86308-7a27-4255-b23c-ce2394f02473)] michael@0: interface jsdIObject : nsISupports michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDObject JSDObject; michael@0: michael@0: /** michael@0: * The URL (filename) that contains the script which caused this object michael@0: * to be created. michael@0: */ michael@0: readonly attribute AUTF8String creatorURL; michael@0: /** michael@0: * Line number in the creatorURL where this object was created. michael@0: */ michael@0: readonly attribute unsigned long creatorLine; michael@0: /** michael@0: * The URL (filename) that contains the script which defined the constructor michael@0: * used to create this object. michael@0: */ michael@0: readonly attribute AUTF8String constructorURL; michael@0: /** michael@0: * Line number in the creatorURL where this object was created. michael@0: */ michael@0: readonly attribute unsigned long constructorLine; michael@0: /** michael@0: * jsdIValue for this object. michael@0: */ michael@0: readonly attribute jsdIValue value; michael@0: }; michael@0: michael@0: /** michael@0: * Representation of a property of an object. When an instance is invalid, all michael@0: * method and property access will result in a NS_UNAVAILABLE error. michael@0: */ michael@0: [scriptable, uuid(acf1329e-aaf6-4d6a-a1eb-f75858566f09)] michael@0: interface jsdIProperty : jsdIEphemeral michael@0: { michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDContext JSDContext; michael@0: /** Internal use only. */ michael@0: [noscript] readonly attribute JSDProperty JSDProperty; michael@0: michael@0: /** michael@0: * FLAG_* values must be kept in sync with JSDPD_* #defines in jsdebug.h. michael@0: */ michael@0: michael@0: /** visible to for/in loop */ michael@0: const unsigned long FLAG_ENUMERATE = 0x01; michael@0: /** assignment is error */ michael@0: const unsigned long FLAG_READONLY = 0x02; michael@0: /** property cannot be deleted */ michael@0: const unsigned long FLAG_PERMANENT = 0x04; michael@0: /** property has an alias id */ michael@0: const unsigned long FLAG_ALIAS = 0x08; michael@0: /** argument to function */ michael@0: const unsigned long FLAG_ARGUMENT = 0x10; michael@0: /** local variable in function */ michael@0: const unsigned long FLAG_VARIABLE = 0x20; michael@0: /** exception occurred looking up property, value is exception */ michael@0: const unsigned long FLAG_EXCEPTION = 0x40; michael@0: /** native getter returned false without throwing an exception */ michael@0: const unsigned long FLAG_ERROR = 0x80; michael@0: /** found via explicit lookup (property defined elsewhere.) */ michael@0: const unsigned long FLAG_HINTED = 0x800; michael@0: michael@0: /** FLAG_* values OR'd together, representing the flags for this property. */ michael@0: readonly attribute unsigned long flags; michael@0: /** jsdIValue representing the alias for this property. */ michael@0: readonly attribute jsdIValue alias; michael@0: /** name for this property. */ michael@0: readonly attribute jsdIValue name; michael@0: /** value of this property. */ michael@0: readonly attribute jsdIValue value; michael@0: };