Labs/Jetpack/Binary Components: Difference between revisions

From MozillaWiki
< Labs‎ | Jetpack
Jump to navigation Jump to search
(→‎Membrane Objects: added docs for membrane.iteratorObject)
(Redirect to memory profiler page)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
= nsJetpack =
#REDIRECT [[Labs/Memory_Profiler]]
 
<code>nsJetpack</code> is a binary component used to provide services to Jetpack that aren't otherwise available to scripted chrome code in the Mozilla platform.
 
== Accessing the Component ==
 
Because the goal of <code>nsJetpack</code> is to provide functionality to scripted code, and because much of its functionality is concerned with providing access to SpiderMonkey internals, the XPCOM interface for the component is rather [http://hg.mozilla.org/labs/jetpack/file/tip/components/public/nsIJetpack.idl trivial].  To obtain the component, simply do:
 
  var nsJetpack = Cc["@labs.mozilla.com/jetpackdi;1"]
                  .createInstance(Ci.nsIJetpack).get();
 
This will give you the <code>nsJetpack</code> native JavaScript object, which provides access to all the component's functionality.
 
== Sample Code ==
 
Sample code for <code>nsJetpack</code> can be found in [http://hg.mozilla.org/labs/jetpack/file/tip/extension/content/js/tests/test-nsjetpack.js test-nsjetpack.js].
 
== Flexible Membrane Functionality ==
 
<code>nsJetpack</code> contains functionality that exposes many SpiderMonkey C API calls to JavaScript, allowing chrome code to create custom membranes (aka wrappers) that allow trusted and untrusted code to interoperate.
 
Aside from security, however, this functionality can also be used to implement APIs that can't normally be implemented using the JavaScript language, such as the <code>window.localStorage</code> interface in HTML5.
 
The source code for this functionality is in [http://hg.mozilla.org/labs/jetpack/file/tip/components/src/wrapper.cpp wrapper.cpp]. 
 
=== Security Concerns ===
 
Note that the Flexible Membrane functionality is intended primarily for prototyping purposes; its use is discouraged in production code for two reasons:
 
# The membrane methods have a tendency to get called very frequently, and as a result, implementing them in JavaScript is likely to not be efficient.
# JavaScript is an inherently dynamic language, and it's very hard to predict what all the possible outcomes of JavaScript code for a membrane might be&mdash;especially when the membrane's script is in the same <code>JSRuntime</code> as the code it's trying to protect.  Because of this, it's hard to code review a Flexible Membrane for security vulnerabilities.
 
Because of these concerns, it's advised that any flexible membranes be re-written in C++ before being reviewed for security and placed in production code.  Before being re-written, however, a test suite should be created for the membrane to ensure that its new implementation has the same characteristics as the original.
 
=== Functions ===
 
<code>nsJetpack.</code>'''wrap'''(''wrappee'', ''membrane'')
 
This function wraps ''wrappee'' with the [[Labs/Jetpack/Binary_Components#Membrane_Objects|Membrane]] ''membrane'' (meaning that ''membrane'' mediates all access to and from ''wrappee'').  The wrapped object is returned.
 
<code>nsJetpack.</code>'''unwrap'''(''wrappedObject'')
 
Removes the membrane from ''wrappedObject'' and returns the wrappee. If ''wrappedObject'' wasn't ever wrapped by ''nsJetpack.''<code>wrap()</code>, this function returns <code>null</code>.
 
<code>nsJetpack.</code>'''getWrapper'''(''wrappedObject'')
 
Returns the membrane for the given ''wrappedObject''. If ''wrappedObject'' wasn't ever wrapped by ''nsJetpack.''<code>wrap()</code>, this function returns <code>null</code>.
 
=== Membrane Objects ===
 
A ''membrane object'' is a user-defined JavaScript object with any of the following optional methods defined:
 
<code>membrane.</code>'''call'''(''wrappee'', ''membrane'', ''thisObj'', ''args'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSClass.call JSClass.call]; alternatively, it could be described as the analog of Python's <code>__call__</code> magic method.  ''thisObj'' is the object that the callee's <code>this</code> variable should be set to, and ''args'' is the array of arguments to be passed to the callee.  This method should return whatever the return value of the callee is, or raise an exception.
 
<code>membrane.</code>'''construct'''(''wrappee'', ''membrane'', ''thisObj'', ''args'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSClass.construct JSClass.construct].  It's just like ''membrane.''<code>call()</code>, only it's called when the call is preceded by the <code>new</code> operator.
 
<code>membrane.</code>'''convert'''(''wrappee'', ''membrane'', ''type'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSClass.convert JSClass.convert], and is called when SpiderMonkey needs to coerce ''wrappee'' to a different type.  ''type'' is a string identifying the name of the desired type to coerce to, and can be anything ordinarily returned by JavaScript's ''typeof'' operator.  The default implementation of this is to call ''wrappee.''<code>valueOf()</code>.
 
'''NOTE:''' Be very careful about implementing this function, as it can easily cause infinite recursion.
 
<code>membrane.</code>'''resolve'''(''wrappee'', ''membrane'', ''name'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSClass.resolve JSClass.resolve].  It's called when the property identified by ''name'' doesn't exist on ''wrappee''.  The membrane should either define ''name'' on ''wrappee'' and return ''wrappee'', or&mdash;if ''name'' doesn't exist&mdash;it should return <code>undefined</code>.
 
<code>membrane.</code>'''enumerate'''(''wrappee'', ''membrane'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSClass.enumerate JSClass.enumerate].  It should return an iterator that iterates through all the property names in ''wrappee''.
 
<code>membrane.</code>'''iteratorObject'''(''wrappee'', ''membrane'', ''keysOnly'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JSExtendedClass.iteratorObject JSExtendedClass.iteratorObject].  If ''keysOnly'' is <code>true</code>, it should return an iterator that iterates through all the property names in ''wrappee''.  Otherwise, it should return an iterator that yields key-value pairs (in an Array object).
 
<code>membrane.</code>'''getProperty'''(''wrappee'', ''membrane'', ''name'', ''defaultValue'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/En/SpiderMonkey/JSAPI_Reference/JSPropertyOp JSClass.getProperty]; alternatively, it could be described as the analog of Python's <code>__getattr__</code> magic method. ''name'' is the name of the property being accessed, and ''defaultValue'' is the value that JavaScript would ordinarily return.  This function should return the value of the property, which may be ''defaultValue'' or something different. Alternatively, the method may also throw an exception.
 
<code>membrane.</code>'''setProperty'''(''wrappee'', ''membrane'', ''name'', ''defaultValue'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/En/SpiderMonkey/JSAPI_Reference/JSPropertyOp JSClass.setProperty]; alternatively, it could be described as the analog of Python's <code>__setattr__</code> magic method. ''name'' is the name of the property being accessed, and ''defaultValue'' is the value that JavaScript would ordinarily set the value of the property to.  This function should return the value to set the property to, which may be ''defaultValue'' or something different. Alternatively, the method may also throw an exception.
 
<code>membrane.</code>'''addProperty'''(''wrappee'', ''membrane'', ''name'', ''defaultValue'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/En/SpiderMonkey/JSAPI_Reference/JSPropertyOp JSClass.addProperty], and is called immediately after a new property has been added to ''wrappee''. ''name'' is the name of the property being accessed, and ''defaultValue'' is the value that JavaScript would ordinarily set the initial value of the property to.  This function should return the initial value to set the property to, which may be ''defaultValue'' or something different. Alternatively, the method may also throw an exception.
 
<code>membrane.</code>'''delProperty'''(''wrappee'', ''membrane'', ''name'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/En/SpiderMonkey/JSAPI_Reference/JSPropertyOp JSClass.delProperty]; alternatively, it could be described as the analog of Python's <code>__delattr__</code> magic method. ''name'' is the name of the property being deleted.  This function should return <code>true</code> if the property can be deleted, and <code>false</code> if not.
 
== Memory Profiling ==
 
<code>nsJetpack</code> contains functionality allowing chrome code to examine the JavaScript heap. The semantics of this are described at a high level in Atul's blog post entitled [http://www.toolness.com/wp/?p=604 Fun with SpiderMonkey]; please read this blog post before reading the rest of this section.
 
The source code for this functionality is in [http://hg.mozilla.org/labs/jetpack/file/tip/components/src/memory_profiler.cpp memory_profiler.cpp].
 
=== Functions ===
 
<code>nsJetpack.</code>'''profileMemory'''(''code'', ''filename'', ''lineNumber'', ''namedObjects'')
 
This function launches a memory profiling JS runtime and executes ''code'' in it. The ''filename'' and ''lineNumber'' information is for error reporting purposes only.
 
''namedObjects'' is an optional object whose properties, called "names", point to objects in the target JS runtime; these objects can be referred to by their names by certain functions in the memory profiling JS runtime.
 
If the final statement of ''code'' results in a string value, this value is copied and passed back as the result of this function.  This allows ''code'' to perform some memory profiling activity and return the results back to the target JS runtime.
 
=== Memory Profiling Globals ===
 
Code running in the memory profiling JS runtime has access to the following global objects and functions.
 
'''ServerSocket'''()
 
This constructor creates a new blocking TCP/IP socket, or [[Labs/Jetpack/Binary_Components#ServerSocket_Objects|ServerSocket]].
 
'''getGCRoots'''()
 
Returns an array of the numeric JavaScript object IDs of the target runtime that are garbage collection roots.
 
'''getObjectInfo'''(''idOrName'')
 
Returns a JSON-able object containing metadata for the object in the target runtime with the given numeric ID or string name. The object may contain any of the following keys:
 
::<code>id</code> - The numeric ID of the object.
 
::<code>nativeClass</code> - The name of the <code>JSClass</code> used by the object.
 
::<code>size</code> - The size of the object, as reported by <code>JS_GetObjectTotalSize()</code>.
 
::<code>parent</code> - The object's <code>__parent__</code> property (i.e., its global scope).
 
::<code>prototype</code> - The object's <code>__proto__</code> property.
 
::<code>wrappedObject</code> - The object ID of the object that this object wraps.
 
::<code>outerObject</code> - The object ID for this object's outer half, if it's the inner half of a [https://developer.mozilla.org/En/SpiderMonkey/Split_object split object].
 
::<code>innerObject</code> - The object ID for this object's inner half, if it's the outer half of a [https://developer.mozilla.org/En/SpiderMonkey/Split_object split object].
 
::<code>children</code> - An array of object IDs corresponding to all the objects that this object references.  Note that these aren't really "children" in a hierarchical sense, but rather in a heap-tracing sense.
 
::<code>functionSize</code> - If this object corresponds to a function, this is the value returned by <code>JS_GetFunctionTotalSize()</code> on the object.
 
::<code>scriptSize</code> - If this object corresponds to a function, this is the value returned by <code>JS_GetScriptTotalSize()</code> on the object.
 
::<code>name</code> - If this object corresponds to a function, this is the function's name.
 
::<code>filename</code> - If this object corresponds to a function, this is the filename in which the function is defined.
 
::<code>lineStart</code> - If this object corresponds to a function, this is the line at which the function's code begins.
 
::<code>lineEnd</code> - If this object corresponds to a function, this is the line at which the function's code ends.
 
'''getNamedObjects'''()
 
Returns a JSON-able object containing a mapping of names to numeric object IDs; this is the "mirror" of the ''namedObjects'' parameter passed to ''nsJetpack.''<code>profileMemory()</code> in the memory profiling runtime.
 
'''TODO:''' Document TCB functions.
 
=== ServerSocket Objects ===
 
<code>ServerSocket.</code>'''bind'''(''ip'', ''port'')
 
Binds the socket to the given ''ip'' and ''port''.
 
<code>ServerSocket.</code>'''listen'''()
 
Configures the socket for listening.
 
<code>ServerSocket.</code>'''accept'''()
 
Blocks until a connection is made on the socket and returns a new <code>ServerSocket</code> object representing the new connection.
 
<code>ServerSocket.</code>'''recv'''(''size'')
 
Receives up to ''size'' bytes of text from the connected client and returns it as a string. If the connection has been closed, <code>null</code> is returned instead.
 
<code>ServerSocket.</code>'''send'''(''text'')
 
Sends the given text to the connected client.
 
<code>ServerSocket.</code>'''close'''()
 
Closes the connection.
 
== Miscellaneous Functions ==
 
The source code for this functionality is in [http://hg.mozilla.org/labs/jetpack/file/tip/components/src/tcb.cpp tcb.cpp].
 
<code>nsJetpack.</code>'''functionInfo'''(''func'')
 
Returns a JSON-able object with the following properties:
 
::<code>filename</code> - The filename in which ''func'' is defined.
::<code>lineNumber</code> - The line number at which ''func'' is defined.
 
<code>nsJetpack.</code>'''seal'''(''object'', ''isDeep'')
 
This is essentially a JavaScript version of [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_SealObject JS_SealObject].
 
Note that according to the documentation for <code>JS_SealObject</code> and John Resig's post on [http://ejohn.org/blog/ecmascript-5-objects-and-properties/ Ecmascript 5], this actually appears to be more similar to ES5's <code>Object.freeze()</code> than it is to ES5's <code>Object.seal()</code>.

Latest revision as of 22:09, 22 April 2010