aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html')
-rw-r--r--files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html221
1 files changed, 221 insertions, 0 deletions
diff --git a/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html
new file mode 100644
index 0000000000..b7cf0168f5
--- /dev/null
+++ b/files/zh-cn/mozilla/projects/rhino/embedding_tutorial/index.html
@@ -0,0 +1,221 @@
+---
+title: 'Tutorial: Embedding Rhino'
+slug: Mozilla/Projects/Rhino/Embedding_tutorial
+translation_of: Mozilla/Projects/Rhino/Embedding_tutorial
+---
+<p>Embedding Rhino can be done simply with good results. With more effort on the part of the embedder, the objects exposed to scripts can be customized further.</p>
+<p>This tutorial leads you through the steps from a simple embedding to more customized, complex embeddings. Fully compilable examples are provided along the way.</p>
+<p>The examples live in the <code>rhino/examples</code> directory in the distribution and in <code>mozilla/js/rhino/examples</code> in cvs. This document will link to them using <a href="http://lxr.mozilla.org/">lxr</a>.</p>
+<p>In this document, JavaScript code will be in <span class="java_js_code">green</span>, Java code will be in <span class="java_js_code">green,</span> and shell logs will be in <span class="shell_logs_code">purple</span>.</p>
+<h2 id="In_this_document">In this document:</h2>
+<ul class="toc">
+ <li><a href="#runScript">RunScript: A simple embedding</a>
+ <ul>
+ <li><a href="#enteringContext">Entering a Context</a></li>
+ <li><a href="#initializing">Initializing standard objects</a></li>
+ <li><a href="#collecting">Collecting the arguments</a></li>
+ <li><a href="#evaluating">Evaluating a script</a></li>
+ <li><a href="#print">Printing the result</a></li>
+ <li><a href="#exit">Exiting the Context</a></li>
+ </ul>
+ </li>
+ <li><a href="#expose">Expose Java APIs</a>
+ <ul>
+ <li><a href="#useJava">Using Java APIs</a></li>
+ <li><a href="#implementingInterfaces">Implementing interfaces</a></li>
+ <li><a href="#addJava">Adding Java objects</a></li>
+ </ul>
+ </li>
+ <li><a href="#usingJSObjs">Using JavaScript objects from Java</a>
+ <ul>
+ <li><a href="#usingJSvars">Using JavaScript variables</a></li>
+ <li><a href="#callingJSfuns">Calling JavaScript functions</a></li>
+ </ul>
+ </li>
+ <li><a href="#javaScriptHostObjects">JavaScript host objects</a>
+ <ul>
+ <li><a href="#definingHostObjects">Defining Host Objects</a></li>
+ <li><a href="#counter">Counter example</a>
+ <ul>
+ <li><a href="#counterCtors">Counter's constructors</a></li>
+ <li><a href="#classname">Class name</a></li>
+ <li><a href="#dynamic">Dynamic properties</a></li>
+ <li><a href="#definingMethods">Defining JavaScript "methods"</a></li>
+ <li><a href="#addingCounter">Adding Counter to RunScript</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<h2 id="RunScript_A_simple_embedding"><a id="runScript" name="runScript">RunScript: A simple embedding</a></h2>
+<p>About the simplest embedding of Rhino possible is the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript.java">RunScript example</a>. All it does it read a script from the command line, execute it, and print a result.</p>
+<p>Here's an example use of RunScript from a shell command line:</p>
+<pre class="code shell_logs_code">$ java RunScript "Math.cos(Math.PI)"
+-1
+$ java RunScript "function f(x){return x+1} f(7)"
+8
+</pre>
+<p>Note that you'll have to have both the Rhino classes and the RunScript example class file in the classpath. Let's step through the body of <code>main</code> one line at time.</p>
+<h3 id="Entering_a_Context"><a id="enteringContext" name="enteringContext">Entering a Context</a></h3>
+<p>The code</p>
+<pre class="code java_js_code">Context cx = Context.enter();
+</pre>
+<p>Creates and enters a <code>Context</code>. A <code>Context</code> stores information about the execution environment of a script.</p>
+<h3 id="Initializing_standard_objects"><a name="initializing">Initializing standard objects</a></h3>
+<p>The code</p>
+<pre class="code java_js_code">Scriptable scope = cx.initStandardObjects();
+</pre>
+<p>Initializes the standard objects (<code>Object</code>, <code>Function</code>, etc.) This must be done before scripts can be executed. The <var>null</var> parameter tells <code>initStandardObjects</code> to create and return a scope object that we use in later calls.</p>
+<h3 id="Collecting_the_arguments"><a id="collecting" name="collecting">Collecting the arguments</a></h3>
+<p>This code is standard Java and not specific to Rhino. It just collects all the arguments and concatenates them together.</p>
+<pre class="code java_js_code">String s = "";
+for (int i=0; i &lt; args.length; i++) {
+ s += args[i];
+}
+</pre>
+<h3 id="Evaluating_a_script"><a id="evaluating" name="evaluating">Evaluating a script</a></h3>
+<p>The code</p>
+<pre class="code java_js_code">Object result = cx.evaluateString(scope, s, "&lt;cmd&gt;", 1, null);
+</pre>
+<p>uses the Context <code>cx</code> to evaluate a string. Evaluation of the script looks up variables in <var>scope</var>, and errors will be reported with the filename <code>&lt;cmd&gt;</code> and line number 1.</p>
+<h3 id="Printing_the_result"><a id="print" name="print">Printing the result</a></h3>
+<p>The code</p>
+<pre class="code java_js_code">System.out.println(cx.toString(result));
+</pre>
+<p>prints the result of evaluating the script (contained in the variable <var>result</var>). <var>result</var> could be a string, JavaScript object, or other values. The <code>toString</code> method converts any JavaScript value to a string.</p>
+<h3 id="Exiting_the_Context"><a id="exit" name="exit">Exiting the Context</a></h3>
+<p>The code</p>
+<pre class="code java_js_code">} finally {
+ Context.exit();
+}
+</pre>
+<p>exits the Context. This removes the association between the Context and the current thread and is an essential cleanup action. There should be a call to <code>exit</code> for every call to <code>enter</code>. To make sure that it is called even if an exception is thrown, it is put into the finally block corresponding to the try block starting after <code>Context.enter()</code>.</p>
+<h2 id="Expose_Java_APIs"><a id="expose" name="expose">Expose Java APIs</a></h2>
+<h3 id="Using_Java_APIs"><a id="useJava" name="useJava">Using Java APIs</a></h3>
+<p>No additional code in the embedding needed! The JavaScript feature called
+ <i>
+ LiveConnect</i>
+ allows JavaScript programs to interact with Java objects:</p>
+<pre class="code shell_logs_code">$ java RunScript "java.lang.System.out.println(3)"
+3.0
+undefined
+</pre>
+<h3 id="Implementing_interfaces"><a id="implementingInterfaces" name="implementingInterfaces">Implementing interfaces</a></h3>
+<p>Using Rhino, JavaScript objects can implement arbitrary Java interfaces. There's no Java code to write -- it's part of Rhino's LiveConnect implementation. For example, we can see how to implement java.lang.Runnable in a Rhino shell session:</p>
+<pre class="code shell_logs_code">js&gt; obj = { run: function() { print("hi"); } }
+[object Object]
+js&gt; obj.run()
+hi
+js&gt; r = new java.lang.Runnable(obj);
+[object Object]
+js&gt; t = new java.lang.Thread(r)
+Thread[Thread-0,5,main]
+js&gt; t.start()
+hi
+</pre>
+<h3 id="Adding_Java_objects"><a id="addJava" name="addJava">Adding Java objects</a></h3>
+<p>The next example is <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript2.java">RunScript2</a>. This is the same as RunScript, but with the addition of two extra lines of code:</p>
+<pre class="code java_js_code">Object wrappedOut = Context.javaToJS(System.out, scope);
+ScriptableObject.putProperty(scope, "out", wrappedOut);
+</pre>
+<p>These lines add a global variable <code>out</code> that is a JavaScript reflection of the <code>System.out</code> variable:</p>
+<pre class="code shell_logs_code">$ java RunScript2 "out.println(42)"
+42.0
+undefined
+</pre>
+<h2 id="Using_JavaScript_objects_from_Java"><a id="usingJSObjs" name="usingJSObjs">Using JavaScript objects from Java</a></h2>
+<p>After evaluating a script it's possible to query the scope for variables and functions, extracting values and calling JavaScript functions. This is illustrated in the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript3.java">RunScript3</a> example. This example adds the ability to print the value of variable <var>x</var> and the result of calling function <code>f</code>. Both <var>x</var> and <var>f</var> are expected to be defined by the evaluated script. For example,</p>
+<pre class="code shell_logs_code">$ java RunScript3 "x = 7"
+x = 7
+f is undefined or not a function.
+$ java RunScript3 "function f(a) { return a; }"
+x is not defined.
+f("my args") = my arg
+</pre>
+<h3 id="Using_JavaScript_variables"><a id="usingJSvars" name="usingJSvars">Using JavaScript variables</a></h3>
+<p>To print out the value of <var>x</var>, we add the following code:</p>
+<pre class="code java_js_code">Object x = scope.get("x", scope);
+if (x == Scriptable.NOT_FOUND) {
+ System.out.println("x is not defined.");
+} else {
+ System.out.println("x = " + Context.toString(x));
+}
+</pre>
+<h3 id="Calling_JavaScript_functions"><a id="callingJSfuns" name="callingJSfuns">Calling JavaScript functions</a></h3>
+<p>To get the function <var>f</var>, call it, and print the result, we add this code:</p>
+<pre class="code java_js_code">Object fObj = scope.get("f", scope);
+if (!(fObj instanceof Function)) {
+ System.out.println("f is undefined or not a function.");
+} else {
+ Object functionArgs[] = { "my arg" };
+ Function f = (Function)fObj;
+ Object result = f.call(cx, scope, scope, functionArgs);
+ String report = "f('my args') = " + Context.toString(result);
+ System.out.println(report);
+}
+</pre>
+<h2 id="JavaScript_host_objects"><a id="javaScriptHostObjects" name="javaScriptHostObjects">JavaScript host objects</a></h2>
+<h3 id="Defining_Host_Objects"><a id="definingHostObjects" name="definingHostObjects">Defining Host Objects</a></h3>
+<p>Custom host objects can implement special JavaScript features like dynamic properties.</p>
+<h3 id="Counter_example"><a id="counter" name="counter">Counter example</a></h3>
+<p>The <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/Counter.java">Counter example</a> is a simple host object. We'll go through it method by method below.</p>
+<p>It's easy to try out new host object classes in the shell using its built-in <code>defineClass</code> function. We'll see how to add it to RunScript later. (Note that because the <code>java -jar</code> option preempts the rest of the classpath, we can't use that and access the <code>Counter</code> class.)</p>
+<pre class="code shell_logs_code">$ java -cp "js.jar;examples" org.mozilla.javascript.tools.shell.Main
+js&gt; defineClass("Counter")
+js&gt; c = new Counter(7)
+[object Counter]
+js&gt; c.count
+7
+js&gt; c.count
+8
+js&gt; c.count
+9
+js&gt; c.resetCount()
+js&gt; c.count
+0
+</pre>
+<h3 id="Counter's_constructors"><a id="counterCtors" name="counterCtors">Counter's constructors</a></h3>
+<p>The zero-argument constructor is used by Rhino runtime to create instances. For the counter example, no initialization work is needed, so the implementation is empty.</p>
+<pre class="code java_js_code">public Counter () { }
+</pre>
+<p>The method <code>jsConstructor</code> defines the JavaScript constructor that was called with the expression <code>new Counter(7)</code> in the JavaScript code above.</p>
+<pre class="code java_js_code">public void jsConstructor(int a) { count
+= a; }
+</pre>
+<h3 id="Class_name"><a id="classname" name="classname">Class name</a></h3>
+<p>The class name is defined by the <code>getClassName</code> method. This is used to determine the name of the constructor.</p>
+<pre class="code java_js_code">public String getClassName() { return "Counter";
+}
+</pre>
+<h3 id="Dynamic_properties"><a id="dynamic" name="dynamic">Dynamic properties</a></h3>
+<p>Dynamic properties are defined by methods beginning with <code>jsGet_</code> or <code>jsSet_</code>. The method <code>jsGet_count</code> defines the
+ <i>
+ count</i>
+ property.</p>
+<pre class="code java_js_code">public int jsGet_count() { return count++;
+}
+</pre>
+<p>The expression <code>c.count</code> in the JavaScript code above results in a call to this method.</p>
+<h3 id="Defining_JavaScript_methods"><a id="definingMethods" name="definingMethods">Defining JavaScript "methods"</a></h3>
+<p>Methods can be defined using the <code>jsFunction_ prefix</code>. Here we define <code>resetCount</code> for JavaScript.</p>
+<pre class="code java_js_code">public void jsFunction_resetCount() { count
+= 0; }
+</pre>
+<p>The call <code>c.resetCount()</code> above calls this method.</p>
+<h3 id="Adding_Counter_to_RunScript"><a id="addingCounter" name="addingCounter">Adding Counter to RunScript</a></h3>
+<p>Now take a look at the <a href="http://lxr.mozilla.org/mozilla/source/js/rhino/examples/RunScript4.java">RunScript4 example</a>. It's the same as RunScript except for two additions. The method <code>ScriptableObject.defineClass</code> uses a Java class to define the Counter "class" in the top-level scope:</p>
+<pre class="code java_js_code">ScriptableObject.defineClass(scope, Counter.class);
+</pre>
+<p>Now we can reference the <code>Counter</code> object from our script:</p>
+<pre class="code shell_logs_code">$ java RunScript4 "c = new Counter(3); c.count;
+c.count;"
+</pre>
+<p>It also creates a new instance of the <code>Counter</code> object from within our Java code, constructing it with the value 7, and assigning it to the top-level variable <code>myCounter</code>:</p>
+<pre class="code java_js_code">Object[] arg = { new Integer(7) };
+Scriptable myCounter = cx.newObject(scope, "Counter", arg);
+scope.put("myCounter", scope, myCounter);
+</pre>
+<p>Now we can reference the <code>myCounter</code> object from our script:</p>
+<pre class="code shell_logs_code">$ java RunScript3 'RunScript4 'myCounter.count; myCounter.count'
+8
+</pre>