~ubuntu-branches/ubuntu/karmic/gears/karmic

« back to all changes in this revision

Viewing changes to gears/base/common/js_standalone_engine_mozjs.cc

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Lesicnik
  • Date: 2009-04-30 19:15:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090430191525-0790sb5wzg8ou0xb
Tags: upstream-0.5.21.0~svn3334+dfsg
ImportĀ upstreamĀ versionĀ 0.5.21.0~svn3334+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2008, Google Inc.
 
2
//
 
3
// Redistribution and use in source and binary forms, with or without 
 
4
// modification, are permitted provided that the following conditions are met:
 
5
//
 
6
//  1. Redistributions of source code must retain the above copyright notice, 
 
7
//     this list of conditions and the following disclaimer.
 
8
//  2. Redistributions in binary form must reproduce the above copyright notice,
 
9
//     this list of conditions and the following disclaimer in the documentation
 
10
//     and/or other materials provided with the distribution.
 
11
//  3. Neither the name of Google Inc. nor the names of its contributors may be
 
12
//     used to endorse or promote products derived from this software without
 
13
//     specific prior written permission.
 
14
//
 
15
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
16
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 
17
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
18
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 
19
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
20
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
21
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
22
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 
23
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 
24
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 
 
26
// Create a SpiderMonkey instance and return an NPAPI wrapper for it.
 
27
 
 
28
#include "gears/base/common/js_standalone_engine.h"
 
29
#include "gears/base/common/js_runner.h"
 
30
#include "gears/base/common/mutex.h"
 
31
#include "gears/base/common/scoped_token.h"
 
32
#ifdef BROWSER_WEBKIT
 
33
#include "gears/base/safari/npapi_patches.h" 
 
34
#endif
 
35
#include "third_party/spidermonkey/gears_include/mozjs_api.h"
 
36
#include "third_party/spidermonkey/gears_npapi_bindings/mozjs_npapi_storage.h"
 
37
#include "third_party/spidermonkey/gears_npapi_bindings/mozjs_npruntime.h"
 
38
 
 
39
// Mutex to guard JSCreateContext calls.
 
40
static Mutex engine_creation_mutex;
 
41
 
 
42
// Defined in js_runner_np.cc
 
43
void HandleJSError(const JsRunner *js_runner, JsErrorInfo &error_info);
 
44
 
 
45
typedef DECLARE_SCOPED_TRAITS(JSContext*, JS_DestroyContext, NULL)
 
46
    JSContextTraits;
 
47
typedef scoped_token<JSContext*, JSContextTraits> scoped_jscontext_ptr;
 
48
 
 
49
// Spidermonkey callback for error handling.
 
50
static void JS_DLL_CALLBACK JsErrorHandler(JSContext *cx, const char *message,
 
51
                                           JSErrorReport *report) {
 
52
  // Ugly hack, without this, if we call a JS error handler from here
 
53
  // then Spidermonkey will bork.
 
54
  JSBool old_val = cx->throwing;
 
55
  cx->throwing = JS_FALSE;
 
56
  
 
57
  JsRunner *js_runner = static_cast<JsRunner*>(JS_GetContextPrivate(cx));
 
58
  if (js_runner && report) {
 
59
    JsErrorInfo error_info;
 
60
    error_info.line = report->lineno + 1; // Reported lines start at zero.
 
61
 
 
62
    // The error message can either be in the separate *message param or in
 
63
    // *report->ucmessage. For example, running the following JS in a worker
 
64
    // causes the separate message param to get used:
 
65
    //   throw new Error("foo")
 
66
    // Other errors cause the report->ucmessage property to get used.
 
67
    //
 
68
    // Mozilla also does this, see:
 
69
    // http://lxr.mozilla.org/mozilla1.8.0/source/dom/src/base/nsJSEnvironment.cpp#163
 
70
    if (report->ucmessage) {
 
71
      error_info.message = reinterpret_cast<const char16 *>(report->ucmessage);
 
72
    } else if (message) {
 
73
      std::string16 message_str;
 
74
      if (UTF8ToString16(message, &message_str)) {
 
75
        error_info.message = message_str;
 
76
      }
 
77
    }
 
78
 
 
79
    HandleJSError(js_runner, error_info);
 
80
    
 
81
    // See comment above.
 
82
    cx->throwing = old_val;
 
83
  }
 
84
}
 
85
 
 
86
#ifdef DEBUG
 
87
static JSBool js_gc(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, 
 
88
                    jsval *rval) {
 
89
  JS_GC(cx);
 
90
  return JS_TRUE;
 
91
}
 
92
    
 
93
static JSBool js_print(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, 
 
94
                       jsval *rval) {
 
95
  JSString *str = JS_ValueToString(cx, argv[0]);
 
96
  printf("script result: %s\n", JS_GetStringBytes(str));
 
97
  return JS_TRUE;
 
98
}
 
99
 
 
100
static JSBool js_break(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, 
 
101
                       jsval *rval) {
 
102
  return JS_TRUE;
 
103
}
 
104
#endif
 
105
 
 
106
 
 
107
// Create a JS context & Engine and return them.
 
108
static bool CreateJSEngine(JsRunner *js_runner, JSRuntime **runtime, 
 
109
                           JSContext **context) {
 
110
  // These are taken from js_runner_ff.cc, if changes are made you'll
 
111
  // probably want to change the values there too.
 
112
#ifdef OS_ANDROID
 
113
  const int kRuntimeMaxBytes = 1 * 1024 * 1024; // Somewhat more sensible.
 
114
#else
 
115
  const int kRuntimeMaxBytes = 64 * 1024 * 1024; // mozilla/.../js.c uses 64 MB
 
116
#endif
 
117
  const int kContextStackChunkSize = 1024; // Firefox often uses 1024;
 
118
                                          // also see js/src/readme.html
 
119
  // Create a new JS Runtime.
 
120
  JSRuntime *rt;
 
121
  {
 
122
      MutexLock lock(&engine_creation_mutex);
 
123
      rt = JS_NewRuntime(kRuntimeMaxBytes);
 
124
  }
 
125
  
 
126
  if (!rt) { return false; }
 
127
  
 
128
  // Initialize a context.
 
129
  scoped_jscontext_ptr cx(JS_NewContext(rt, kContextStackChunkSize));
 
130
  if (!cx.get()) {
 
131
    return false;
 
132
  }
 
133
  
 
134
  // Setup context
 
135
  // VAROBJFIX is recommended in /mozilla/js/src/jsapi.h
 
136
  JS_SetOptions(cx.get(), JS_GetOptions(cx.get()) | JSOPTION_VAROBJFIX);
 
137
  JS_SetErrorReporter(cx.get(), JsErrorHandler); 
 
138
  JS_SetContextPrivate(cx.get(), reinterpret_cast<void*>(js_runner));
 
139
  
 
140
  // These structs are static because they must live for duration of JS engine.
 
141
  // SpiderMonkey README also suggests using static for one-off objects.
 
142
  static JSClass global_class = {
 
143
      "Global", 0, // name, flags
 
144
      JS_PropertyStub, JS_PropertyStub,  // defineProperty, deleteProperty
 
145
      JS_PropertyStub, JS_PropertyStub, // getProperty, setProperty
 
146
      JS_EnumerateStub, JS_ResolveStub, // enum, resolve
 
147
      JS_ConvertStub, JS_FinalizeStub // convert, finalize
 
148
  };
 
149
  
 
150
  JSAutoRequest context_lock(cx.get());
 
151
  JSObject *global_obj = JS_NewObject(cx.get(), &global_class, 0, 0);
 
152
  if (!global_obj) { return false; }
 
153
 
 
154
  JSBool js_ok = JS_InitStandardClasses(cx.get(), global_obj);
 
155
  if (!js_ok) { return false; }
 
156
  
 
157
#ifdef DEBUG
 
158
  JS_DefineFunction(cx.get(), global_obj, "print", js_print, 1, 0);
 
159
  JS_DefineFunction(cx.get(), global_obj, "GearsInternalCollectGarbage", js_gc, 
 
160
                    1, 0);
 
161
  JS_DefineFunction(cx.get(), global_obj, "brk", js_break, 
 
162
                    1, 0);
 
163
#endif
 
164
  
 
165
  // Everything is setup, so pass out the JSContext.
 
166
  *runtime = rt;
 
167
  *context = cx.release();
 
168
  return true;
 
169
}
 
170
 
 
171
bool JSStandaloneEngine::InitEngine(JsRunner *js_runner,
 
172
                                    NPP_t *np_instance) {
 
173
  assert(js_runner);
 
174
  assert(np_instance);
 
175
  
 
176
  // Bootstrap the JS Engine instance.
 
177
  JSRuntime *runtime;
 
178
  JSContext *context;
 
179
  if (!CreateJSEngine(js_runner, &runtime, &context)) {
 
180
    return false; 
 
181
  }
 
182
    
 
183
  // Setup the global object
 
184
  // JsRunner is the browser side.
 
185
  (np_instance)->ndata = static_cast<void *>(js_runner);
 
186
  
 
187
  // for use by the plugin side.
 
188
  (np_instance)->pdata = NULL;
 
189
  
 
190
  SpiderMonkeyNPAPIBindings::NPAPI_Storage::CreateThreadLocals(runtime, 
 
191
                                                               context, 
 
192
                                                               np_instance);
 
193
  
 
194
  return true;
 
195
}
 
196
 
 
197
void JSStandaloneEngine::GetNPNEntryPoints(NPNetscapeFuncs *browser_funcs) {
 
198
  assert(browser_funcs);
 
199
#ifdef BROWSER_WEBKIT
 
200
  memset(browser_funcs, 0, sizeof(GearsNPNetscapeFuncs));
 
201
  browser_funcs->size = sizeof(GearsNPNetscapeFuncs);
 
202
#else
 
203
  memset(browser_funcs, 0, sizeof(NPNetscapeFuncs));
 
204
  browser_funcs->size = sizeof(browser_funcs);
 
205
#endif
 
206
  browser_funcs->version = 1;
 
207
  browser_funcs->memalloc = SpiderMonkeyNPAPIBindings::NPN_MemAlloc;
 
208
  browser_funcs->memfree = SpiderMonkeyNPAPIBindings::NPN_MemFree;
 
209
  browser_funcs->getvalue = SpiderMonkeyNPAPIBindings::NPN_GetValue;
 
210
  browser_funcs->releasevariantvalue = 
 
211
      SpiderMonkeyNPAPIBindings::NPN_ReleaseVariantValue;
 
212
  browser_funcs->getstringidentifier = 
 
213
      SpiderMonkeyNPAPIBindings::NPN_GetStringIdentifier;
 
214
  browser_funcs->getstringidentifiers = 
 
215
      SpiderMonkeyNPAPIBindings::NPN_GetStringIdentifiers;
 
216
  browser_funcs->getintidentifier = 
 
217
      SpiderMonkeyNPAPIBindings::NPN_GetIntIdentifier;
 
218
  browser_funcs->identifierisstring = 
 
219
      SpiderMonkeyNPAPIBindings::NPN_IdentifierIsString;
 
220
  browser_funcs->utf8fromidentifier = 
 
221
      SpiderMonkeyNPAPIBindings::NPN_UTF8FromIdentifier;
 
222
#ifdef BROWSER_WEBKIT
 
223
  browser_funcs->intfromidentifier =
 
224
      reinterpret_cast<void * (*)(void *)>(
 
225
          SpiderMonkeyNPAPIBindings::NPN_IntFromIdentifier);
 
226
#else
 
227
  browser_funcs->intfromidentifier =
 
228
      SpiderMonkeyNPAPIBindings::NPN_IntFromIdentifier;
 
229
#endif
 
230
  browser_funcs->createobject = SpiderMonkeyNPAPIBindings::NPN_CreateObject;
 
231
  browser_funcs->retainobject = SpiderMonkeyNPAPIBindings::NPN_RetainObject;
 
232
  browser_funcs->releaseobject = SpiderMonkeyNPAPIBindings::NPN_ReleaseObject;
 
233
  browser_funcs->invoke = SpiderMonkeyNPAPIBindings::NPN_Invoke;
 
234
  browser_funcs->invokeDefault = SpiderMonkeyNPAPIBindings::NPN_InvokeDefault;
 
235
  browser_funcs->evaluate = SpiderMonkeyNPAPIBindings::NPN_Evaluate;
 
236
  browser_funcs->getproperty = SpiderMonkeyNPAPIBindings::NPN_GetProperty;
 
237
  browser_funcs->setproperty = SpiderMonkeyNPAPIBindings::NPN_SetProperty;
 
238
  browser_funcs->removeproperty = SpiderMonkeyNPAPIBindings::NPN_RemoveProperty;
 
239
  browser_funcs->hasproperty = SpiderMonkeyNPAPIBindings::NPN_HasProperty;
 
240
  browser_funcs->hasmethod = SpiderMonkeyNPAPIBindings::NPN_HasMethod;
 
241
  browser_funcs->setexception = SpiderMonkeyNPAPIBindings::NPN_SetException;
 
242
#ifdef BROWSER_WEBKIT
 
243
  ((GearsNPNetscapeFuncs *)browser_funcs)->enumerate = 
 
244
                              SpiderMonkeyNPAPIBindings::NPN_Enumerate;
 
245
#else
 
246
  browser_funcs->enumerate = SpiderMonkeyNPAPIBindings::NPN_Enumerate;
 
247
#endif
 
248
}
 
249
 
 
250
bool JSStandaloneEngine::TerminateEngine() {
 
251
  JSContext * context = 
 
252
      SpiderMonkeyNPAPIBindings::NPAPI_Storage::GetCurrentJSContext();
 
253
  JSRuntime *runtime =
 
254
      SpiderMonkeyNPAPIBindings::NPAPI_Storage::GetsJSRuntime();
 
255
  JS_DestroyContext(context);
 
256
  JS_DestroyRuntime(runtime);
 
257
  SpiderMonkeyNPAPIBindings::NPAPI_Storage::ClearJSContext();
 
258
  return true;
 
259
}