1 #include "jsapi.h"
2
3 #include "ADM_assert.h"
4 #include "SpiderMonkeyEngine.h"
5 #include "SpiderMonkeyScriptWriter.h"
6
7 #include "src_dialogFactory/ADM_JSDFMenu.h"
8 #include "src_dialogFactory/ADM_JSDFToggle.h"
9 #include "src_dialogFactory/ADM_JSDFInteger.h"
10 #include "src_dialogFactory/ADM_JSDialogFactory.h"
11
12 #include "ADM_scriptDFMenu.h"
13 #include "ADM_scriptDFToggle.h"
14 #include "ADM_scriptDFInteger.h"
15 #include "ADM_scriptDialogFactory.h"
16
17 using namespace std;
18
19 extern "C"
20 {
21 JSFunctionSpec *jsGetIfFunctions(void);
22 JSFunctionSpec *jsGetTestFunctions(void);
23 JSFunctionSpec *jsGetAdmFunctions(void);
24 JSFunctionSpec *jsGetEditFunctions(void);
25 JSFunctionSpec *jsGetDialogFactoryFunctions(void);
26 JSObject *jsEditorInit(JSContext *cx, JSObject *obj);
27 JSObject *jsAvidemuxInit(JSContext *cx, JSObject *obj);
28
createEngine()29 IScriptEngine* createEngine()
30 {
31 return new SpiderMonkeyEngine();
32 }
33 }
34
35 JSClass SpiderMonkeyEngine::_globalClass =
36 {
37 "global", JSCLASS_GLOBAL_FLAGS,
38 JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
39 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
40 JSCLASS_NO_OPTIONAL_MEMBERS
41 };
42
~SpiderMonkeyEngine()43 SpiderMonkeyEngine::~SpiderMonkeyEngine()
44 {
45 this->callEventHandlers(IScriptEngine::Information, NULL, -1, "Closing Spidermonkey");
46
47 JS_DestroyContext(_jsContext);
48 JS_DestroyRuntime(_jsRuntime);
49 }
50
name()51 string SpiderMonkeyEngine::name()
52 {
53 return "SpiderMonkey";
54 }
55
initialise(IEditor * editor)56 void SpiderMonkeyEngine::initialise(IEditor *editor)
57 {
58 ADM_assert(editor);
59
60 _editor = editor;
61
62 _jsRuntime = JS_NewRuntime(1000000L);
63 ADM_assert(_jsRuntime);
64
65 _jsContext = JS_NewContext(_jsRuntime, 8192);
66 ADM_assert(_jsContext);
67
68 JS_SetContextPrivate(_jsContext, this);
69
70 _jsObject = JS_NewObject(_jsContext, &_globalClass, 0, 0);
71 ADM_assert(_jsObject);
72
73 ADM_assert(JS_InitStandardClasses(_jsContext, _jsObject) == JS_TRUE);
74
75 JS_SetErrorReporter(_jsContext, SpiderMonkeyEngine::printError);
76
77 this->registerFunctions(_jsContext, _jsObject);
78 this->registerDialogFunctions(_jsContext, _jsObject);
79 this->callEventHandlers(IScriptEngine::Information, NULL, -1, "Spidermonkey initialised");
80 }
81
registerFunctions(JSContext * cx,JSObject * obj)82 void SpiderMonkeyEngine::registerFunctions(JSContext *cx, JSObject *obj)
83 {
84 this->registerFunctionGroup("Debug", "", jsGetIfFunctions(), cx, obj);
85 this->registerFunctionGroup("Test", "", jsGetTestFunctions(), cx, obj);
86
87 // Register also our class (for help() )
88 JsHook h;
89 h.name = "adm";
90 h.text = "Please prefix this with adm.";
91 h.jsFunctions = jsGetAdmFunctions();
92
93 jsHooks.push_back(h);
94 jsAvidemuxInit(cx, obj);
95
96 // Register also edit
97 h.name = "editor";
98 h.text = "Please prefix this with editor.";
99 h.jsFunctions = jsGetEditFunctions();
100 jsEditorInit(cx, obj);
101 jsHooks.push_back(h);
102 }
103
registerDialogFunctions(JSContext * cx,JSObject * obj)104 void SpiderMonkeyEngine::registerDialogFunctions(JSContext *cx, JSObject *obj)
105 {
106 ADM_assert(ADM_JSDialogFactory::JSInit(cx, obj) != NULL);
107 ADM_assert(ADM_JSDFMenu::JSInit(cx, obj) != NULL);
108 ADM_assert(ADM_JSDFToggle::JSInit(cx, obj) != NULL);
109 ADM_assert(ADM_JSDFInteger::JSInit(cx, obj) != NULL);
110
111 this->callEventHandlers(IScriptEngine::Information, NULL, -1, "Registered DialogFactory classes");
112 }
113
registerFunctionGroup(const char * name,const char * text,JSFunctionSpec * s,JSContext * cx,JSObject * obj)114 void SpiderMonkeyEngine::registerFunctionGroup(const char *name, const char *text, JSFunctionSpec *s, JSContext *cx, JSObject *obj)
115 {
116 assert(JS_DefineFunctions(cx, obj, s) == JS_TRUE);
117
118 this->callEventHandlers(IScriptEngine::Information, NULL, -1,
119 (string("Registered ") + string(name) + string(" functions")).c_str());
120
121 JsHook h;
122
123 h.name = name;
124 h.text = text;
125 h.jsFunctions = s;
126
127 jsHooks.push_back(h);
128 }
129
printError(JSContext * cx,const char * message,JSErrorReport * report)130 void SpiderMonkeyEngine::printError(JSContext *cx, const char *message, JSErrorReport *report)
131 {
132 SpiderMonkeyEngine *engine = (SpiderMonkeyEngine*)JS_GetContextPrivate(cx);
133
134 engine->callEventHandlers(IScriptEngine::Error, report->filename, report->lineno, message);
135 }
136
registerEventHandler(eventHandlerFunc * func)137 void SpiderMonkeyEngine::registerEventHandler(eventHandlerFunc *func)
138 {
139 _eventHandlerSet.insert(func);
140 }
141
unregisterEventHandler(eventHandlerFunc * func)142 void SpiderMonkeyEngine::unregisterEventHandler(eventHandlerFunc *func)
143 {
144 _eventHandlerSet.erase(func);
145 }
146
callEventHandlers(EventType eventType,const char * fileName,int lineNo,const char * message)147 void SpiderMonkeyEngine::callEventHandlers(EventType eventType, const char *fileName, int lineNo, const char *message)
148 {
149 EngineEvent event = { this, eventType, fileName, lineNo, message };
150 set<eventHandlerFunc*>::iterator it;
151
152 for (it = _eventHandlerSet.begin(); it != _eventHandlerSet.end(); ++it)
153 {
154 (*it)(&event);
155 }
156 }
157
runScript(string script,RunMode mode)158 bool SpiderMonkeyEngine::runScript(string script, RunMode mode)
159 {
160 jsval rval;
161
162 return JS_EvaluateScript(_jsContext, _jsObject, script.c_str(), script.length(), "dummy", 1, &rval) == JSVAL_TRUE;
163 }
164
runScriptFile(string name,RunMode mode)165 bool SpiderMonkeyEngine::runScriptFile(string name, RunMode mode)
166 {
167 jsval rval;
168 uintN lineno = 0;
169 bool success = false;
170
171 this->callEventHandlers(IScriptEngine::Information, NULL, -1,
172 (string("Compiling \"" + string(name) + string("\"...")).c_str()));
173 JSScript *pJSScript = JS_CompileFile(_jsContext, _jsObject, name.c_str());
174 this->callEventHandlers(IScriptEngine::Information, NULL, -1, "Done.");
175
176 if (pJSScript != NULL)
177 {
178 this->callEventHandlers(IScriptEngine::Information, NULL, -1,
179 (string("Executing ") + string(name) + string("...")).c_str());
180
181 JSBool ok = JS_ExecuteScript(_jsContext, _jsObject, pJSScript, &rval);
182 JS_DestroyScript(_jsContext, pJSScript);
183
184 this->callEventHandlers(IScriptEngine::Information, NULL, -1, "Done");
185 }
186
187 JS_GC(_jsContext);
188
189 return success;
190 }
191
editor()192 IEditor* SpiderMonkeyEngine::editor()
193 {
194 return _editor;
195 }
196
capabilities()197 IScriptEngine::Capabilities SpiderMonkeyEngine::capabilities()
198 {
199 return IScriptEngine::None;
200 }
201
createScriptWriter()202 IScriptWriter* SpiderMonkeyEngine::createScriptWriter()
203 {
204 return new SpiderMonkeyScriptWriter();
205 }
206
openDebuggerShell()207 void SpiderMonkeyEngine::openDebuggerShell() {}
208
defaultFileExtension()209 string SpiderMonkeyEngine::defaultFileExtension()
210 {
211 return "js";
212 }
213
maturityRanking()214 int SpiderMonkeyEngine::maturityRanking()
215 {
216 return 0;
217 }
218
referenceUrl()219 string SpiderMonkeyEngine::referenceUrl()
220 {
221 return "";
222 }
223