KJsEmbed

kjsembed.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2005, 2006 Ian Reinhart Geiser <[email protected]>
3  Copyright (C) 2005, 2006 Matt Broadstone <[email protected]>
4  Copyright (C) 2005, 2006 Richard J. Moore <[email protected]>
5  Copyright (C) 2005, 2006 Erik L. Bunce <[email protected]>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 #include "kjsembed.h"
23 #include "binding_support.h"
24 
25 #include "qobject_binding.h"
26 #include "variant_binding.h"
27 #include "static_binding.h"
28 
29 #include "iosupport.h"
30 #include "quiloader_binding.h"
31 #ifdef KJSEMBED_FORMBUILDER_BINDING
32 #include "qformbuilder_binding.h"
33 #endif
34 #include "qpainter_binding.h"
35 #include "qwidget_binding.h"
36 #include "qaction_binding.h"
37 #include "qlayout_binding.h"
38 #include "svg_binding.h"
39 #include "filedialog_binding.h"
40 #include "settings.h"
41 #include "fileio.h"
42 #include "color.h"
43 #include "rect.h"
44 #include "size.h"
45 #include "point.h"
46 #include "image.h"
47 #include "pixmap.h"
48 #include "brush.h"
49 #include "pen.h"
50 #include "font.h"
51 #include "dom.h"
52 #include "url.h"
53 #include "application.h"
54 
55 #include "builtins.h"
56 
57 #include <kjs/interpreter.h>
58 #include <kjs/completion.h>
59 
60 #include <QFile>
61 #include <QTextStream>
62 #include <QObject>
63 
64 #include <QDebug>
65 
66 /**
67 * Implement QString-KJS::UString conversion methods. These methods are declared
68 * by KJS, but libkjs doesn't actually contain their implementations.
69 * because we link against khtml , those functions are already implemented there.
70 *
71 */
72 namespace KJS
73 {
74 #ifndef QTONLY_WEBKIT
75 UString::UString(const QString &d)
76 {
77  uint len = d.length();
78  UChar *dat = static_cast<UChar *>(fastMalloc(sizeof(UChar) * len));
79  memcpy(dat, d.unicode(), len * sizeof(UChar));
80  m_rep = UString::Rep::create(dat, len);
81 }
82 
84 {
85  return QString((QChar *) data(), size());
86 }
87 
89 {
90  return QString((QChar *) data(), size());
91 }
92 #endif
93 }
94 
95 namespace KJSEmbed
96 {
97 
98 class EnginePrivate
99 {
100 public:
101  EnginePrivate()
102  {
103  m_interpreter = new KJS::Interpreter();
104  m_interpreter->initGlobalObject();
105  m_interpreter->ref();
106  }
107  ~EnginePrivate()
108  {
109  m_interpreter->deref();
110  }
111  KJS::Interpreter *m_interpreter;
112  KJS::Completion m_currentResult;
113  bool m_bindingsEnabled;
114 };
115 
116 void setup(KJS::ExecState *exec, KJS::JSObject *parent)
117 {
118  StaticBinding::publish(exec, parent, IoFactory::methods()); // Global methods
119  StaticBinding::publish(exec, parent, FileDialog::methods()); // Global methods
120  StaticBinding::publish(exec, parent, BuiltinsFactory::methods()); // Global methods
121  StaticConstructor::add(exec, parent, FileIO::constructor()); // Ctor
122  StaticConstructor::add(exec, parent, DomNode::constructor()); // Ctor
123  StaticConstructor::add(exec, parent, DomDocument::constructor()); // Ctor
124  StaticConstructor::add(exec, parent, DomElement::constructor()); // Ctor
125  StaticConstructor::add(exec, parent, DomAttr::constructor()); // Ctor
126  StaticConstructor::add(exec, parent, DomDocumentType::constructor()); // Ctor
127  StaticConstructor::add(exec, parent, DomNodeList::constructor()); // Ctor
128  StaticConstructor::add(exec, parent, DomNamedNodeMap::constructor()); // Ctor
129  StaticConstructor::add(exec, parent, DomText::constructor()); // Ctor
130  StaticConstructor::add(exec, parent, Url::constructor()); // Ctor
131  StaticConstructor::add(exec, parent, SettingsBinding::constructor()); // Ctor
132  StaticConstructor::add(exec, parent, CoreApplicationBinding::constructor());
133  StaticConstructor::add(exec, parent, Point::constructor()); // Ctor
134  StaticConstructor::add(exec, parent, Size::constructor()); // Ctor
135  StaticConstructor::add(exec, parent, Rect::constructor()); // Ctor
136  StaticConstructor::add(exec, parent, Color::constructor()); // Ctor
137 
138  // check if this is a GUI application
139  QApplication *app = ::qobject_cast<QApplication *>(QCoreApplication::instance());
140  if (app) {
141  //qDebug("Loading GUI Bindings");
142 
143 #ifdef KJSEMBED_FORMBUILDER_BINDING
144  StaticConstructor::add(exec, parent, FormBuilder::constructor()); // Ctor
145 #endif
146  StaticConstructor::add(exec, parent, UiLoaderBinding::constructor()); // Ctor
147  StaticConstructor::add(exec, parent, QWidgetBinding::constructor()); // Ctor
148  StaticConstructor::add(exec, parent, Layout::constructor()); // Ctor
149  StaticConstructor::add(exec, parent, Action::constructor()); // Ctor
150  StaticConstructor::add(exec, parent, ActionGroup::constructor()); // Ctor
151  StaticConstructor::add(exec, parent, Font::constructor()); // Ctor
152  StaticConstructor::add(exec, parent, Pen::constructor()); // Ctor
153  StaticConstructor::add(exec, parent, Brush::constructor()); // Ctor
154  StaticConstructor::add(exec, parent, Image::constructor()); // Ctor
155  StaticConstructor::add(exec, parent, Pixmap::constructor()); // Ctor
156  StaticConstructor::add(exec, parent, Painter::constructor()); // Ctor
157  StaticConstructor::add(exec, parent, SvgRenderer::constructor()); // Ctor
158  StaticConstructor::add(exec, parent, SvgWidget::constructor()); // Ctor
159  StaticConstructor::add(exec, parent, ApplicationBinding::constructor());
160  }
161 }
162 
163 Engine::Engine(bool enableBindings)
164 {
165  dptr = new EnginePrivate();
166  if (enableBindings) {
167  setup(dptr->m_interpreter->globalExec(), dptr->m_interpreter->globalObject());
168  }
169  dptr->m_bindingsEnabled = enableBindings;
170 }
171 
173 {
174  delete dptr;
175 }
176 
178 {
179  return dptr->m_bindingsEnabled;
180 }
181 
182 KJS::JSObject *Engine::addObject(QObject *obj, KJS::JSObject *parent, const KJS::UString &name) const
183 {
184  KJS::ExecState *exec = dptr->m_interpreter->globalExec();
185  KJS::JSObject *returnObject = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::CPPOwned);
186  KJS::Identifier jsName(!name.isEmpty() ? name : toUString(obj->objectName()));
187 
188  parent->putDirect(jsName, returnObject, KJS::DontDelete | KJS::ReadOnly);
189  return returnObject;
190 }
191 
192 KJS::JSObject *Engine::addObject(QObject *obj, const KJS::UString &name) const
193 {
194  return addObject(obj, dptr->m_interpreter->globalObject(), name);
195 }
196 
198 {
199  return dptr->m_currentResult;
200 }
201 
203 {
204  return dptr->m_interpreter;
205 }
206 
208 {
209 // qDebug() << "runFile: " << toQString(fileName);
210  KJS::UString code;
211  QFile file(toQString(fileName));
212  if (file.open(QFile::ReadOnly)) {
213  QTextStream ts(&file);
214 
215  QString line;
216  while (!ts.atEnd()) {
217  line = ts.readLine();
218  if (line[0] != '#') {
219  code += toUString(line + '\n');
220  }
221  }
222  file.close();
223  } else {
224  code = "println('Could not open file.');";
225  qWarning() << "Could not open file " << toQString(fileName);
226  }
227 
228 // qDebug() << "Loaded code: " << toQString(code);
229 
230  return interpreter->evaluate(fileName, 0, code, nullptr);
231 }
232 
234 {
235  dptr->m_currentResult = runFile(dptr->m_interpreter, fileName);
236 
237  if (dptr->m_currentResult.complType() == KJS::Normal) {
238  return Engine::Success;
239  } else if (dptr->m_currentResult.complType() == KJS::ReturnValue) {
240  return Engine::Success;
241  } else {
242  return Engine::Failure;
243  }
244 }
245 
247 {
248  dptr->m_currentResult = dptr->m_interpreter->evaluate(KJS::UString(""), 0, code, nullptr);
249  if (dptr->m_currentResult.complType() == KJS::Normal) {
250  return Engine::Success;
251  } else if (dptr->m_currentResult.complType() == KJS::ReturnValue) {
252  return Engine::Success;
253  } else {
254  return Engine::Failure;
255  }
256 }
257 
258 KJS::JSObject *Engine::construct(const KJS::UString &className, const KJS::List &args) const
259 {
260  KJS::JSObject *global = dptr->m_interpreter->globalObject();
261  KJS::ExecState *exec = dptr->m_interpreter->globalExec();
262  return StaticConstructor::construct(exec, global, className, args);
263 }
264 
265 KJS::JSValue *Engine::callMethod(const KJS::UString &methodName, const KJS::List &args)
266 {
267  KJS::JSObject *global = dptr->m_interpreter->globalObject();
268  KJS::ExecState *exec = dptr->m_interpreter->globalExec();
269 
270  KJS::Identifier id = KJS::Identifier(KJS::UString(methodName));
271  KJS::JSObject *fun = global->get(exec, id)->toObject(exec);
272  KJS::JSValue *retValue;
273 
274  if (!fun->implementsCall()) {
275  QString msg = i18n("%1 is not a function and cannot be called.", toQString(methodName));
276  return throwError(exec, KJS::TypeError, msg);
277  }
278 
279  retValue = fun->call(exec, global, args);
280 
281  if (exec->hadException()) {
282  return exec->exception();
283  }
284 
285  return retValue;
286 }
287 
288 KJS::JSValue *Engine::callMethod(KJS::JSObject *parent,
289  const KJS::UString &methodName, const KJS::List &args)
290 {
291  KJS::ExecState *exec = dptr->m_interpreter->globalExec();
292 
293  KJS::Identifier id = KJS::Identifier(methodName);
294  KJS::JSObject *fun = parent->get(exec, id)->toObject(exec);
295  KJS::JSValue *retValue;
296 
297  if (!fun->implementsCall()) {
298  QString msg = i18n("%1 is not a function and cannot be called.", toQString(methodName));
299  return throwError(exec, KJS::TypeError, msg);
300  }
301 
302  retValue = fun->call(exec, parent, args);
303 
304  if (exec->hadException()) {
305  return exec->exception();
306  }
307 
308  return retValue;
309 }
310 
311 } // namespace KJS
312 
ExitStatus
Status codes for script execution.
Definition: kjsembed.h:65
KJS::Completion completion() const
Returns the Completion object for the last script executed.
Definition: kjsembed.cpp:197
virtual bool open(QIODevice::OpenMode mode) override
int size() const
Implement QString-KJS::UString conversion methods.
const QChar * unicode() const const
KJS::JSValue * callMethod(const KJS::UString &methodName, const KJS::List &args=KJS::List())
Execute a method at the global scope of the javascript interpreter.
Definition: kjsembed.cpp:265
Engine(bool enableBindings=true)
Constructs an embedded JS engine.
Definition: kjsembed.cpp:163
KJS::JSObject * addObject(QObject *obj, const KJS::UString &name=KJS::UString()) const
publishes a QObject to the global context of the javascript interpereter.
Definition: kjsembed.cpp:192
bool hadException() const
KJS_EXTERNAL_EXPORT QString qstring() const
Definition: kjsembed.cpp:83
virtual ~Engine()
Clean up.
Definition: kjsembed.cpp:172
ExitStatus runFile(const KJS::UString &file)
Execute the file with the specified name using the current interpreter.
Definition: kjsembed.cpp:233
QString i18n(const char *text, const TYPE &arg...)
bool atEnd() const const
static KJS::JSObject * add(KJS::ExecState *exec, KJS::JSObject *object, const Constructor *constructor)
Add the constructor to an object.
bool isEmpty() const const
int length() const const
QString readLine(qint64 maxlen)
QCoreApplication * instance()
KJS::JSObject * construct(KJS::ExecState *exec, const KJS::List &args) override
Calls the callback that will in turn create a new instance of this object with the arguments passed i...
virtual void close() override
KJS::Interpreter * interpreter() const
Returns the current interpreter.
Definition: kjsembed.cpp:202
static void publish(KJS::ExecState *exec, KJS::JSObject *object, const Method *methods)
Publishes an array of Methods to an object.
const UChar * data() const
const UChar * data() const
Completion evaluate(const UString &sourceURL, int startingLineNumber, const UChar *code, int codeLength, JSValue *thisV=nullptr)
ExitStatus execute(const KJS::UString &code)
Execute a code string using the current interpreter.
Definition: kjsembed.cpp:246
KJS::JSObject * construct(const KJS::UString &className, const KJS::List &args=KJS::List()) const
Create a new instance of an object that the Javascript engine knows about.
Definition: kjsembed.cpp:258
int size() const
JSValue * exception() const
KJS_EXTERNAL_EXPORT QString qstring() const
Definition: kjsembed.cpp:88
bool isBindingsEnabled() const
Returns true if the Engine was created with the bindings enabled.
Definition: kjsembed.cpp:177
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Dec 7 2023 04:05:14 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.