File indexing completed on 2023-12-03 07:47:00
0001 /* This file is part of the KDE libraries 0002 Copyright (C) 2005, 2006 Ian Reinhart Geiser <geiseri@kde.org> 0003 Copyright (C) 2005, 2006 Matt Broadstone <mbroadst@gmail.com> 0004 Copyright (C) 2005, 2006 Richard J. Moore <rich@kde.org> 0005 Copyright (C) 2005, 2006 Erik L. Bunce <kde@bunce.us> 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License as published by the Free Software Foundation; either 0010 version 2 of the License, or (at your option) any later version. 0011 0012 This library is distributed in the hope that it will be useful, 0013 but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 Library General Public License for more details. 0016 0017 You should have received a copy of the GNU Library General Public License 0018 along with this library; see the file COPYING.LIB. If not, write to 0019 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 Boston, MA 02110-1301, USA. 0021 */ 0022 #include "kjsembed.h" 0023 #include "binding_support.h" 0024 0025 #include "qobject_binding.h" 0026 #include "variant_binding.h" 0027 #include "static_binding.h" 0028 0029 #include "iosupport.h" 0030 #include "quiloader_binding.h" 0031 #ifdef KJSEMBED_FORMBUILDER_BINDING 0032 #include "qformbuilder_binding.h" 0033 #endif 0034 #include "qpainter_binding.h" 0035 #include "qwidget_binding.h" 0036 #include "qaction_binding.h" 0037 #include "qlayout_binding.h" 0038 #include "svg_binding.h" 0039 #include "filedialog_binding.h" 0040 #include "settings.h" 0041 #include "fileio.h" 0042 #include "color.h" 0043 #include "rect.h" 0044 #include "size.h" 0045 #include "point.h" 0046 #include "image.h" 0047 #include "pixmap.h" 0048 #include "brush.h" 0049 #include "pen.h" 0050 #include "font.h" 0051 #include "dom.h" 0052 #include "url.h" 0053 #include "application.h" 0054 0055 #include "builtins.h" 0056 0057 #include <kjs/interpreter.h> 0058 #include <kjs/completion.h> 0059 0060 #include <QFile> 0061 #include <QTextStream> 0062 #include <QObject> 0063 0064 #include <QDebug> 0065 0066 /** 0067 * Implement QString-KJS::UString conversion methods. These methods are declared 0068 * by KJS, but libkjs doesn't actually contain their implementations. 0069 * because we link against khtml , those functions are already implemented there. 0070 * 0071 */ 0072 namespace KJS 0073 { 0074 #ifndef QTONLY_WEBKIT 0075 UString::UString(const QString &d) 0076 { 0077 uint len = d.length(); 0078 UChar *dat = static_cast<UChar *>(fastMalloc(sizeof(UChar) * len)); 0079 memcpy(dat, d.unicode(), len * sizeof(UChar)); 0080 m_rep = UString::Rep::create(dat, len); 0081 } 0082 0083 QString UString::qstring() const 0084 { 0085 return QString((QChar *) data(), size()); 0086 } 0087 0088 QString Identifier::qstring() const 0089 { 0090 return QString((QChar *) data(), size()); 0091 } 0092 #endif 0093 } 0094 0095 namespace KJSEmbed 0096 { 0097 0098 class EnginePrivate 0099 { 0100 public: 0101 EnginePrivate() 0102 { 0103 m_interpreter = new KJS::Interpreter(); 0104 m_interpreter->initGlobalObject(); 0105 m_interpreter->ref(); 0106 } 0107 ~EnginePrivate() 0108 { 0109 m_interpreter->deref(); 0110 } 0111 KJS::Interpreter *m_interpreter; 0112 KJS::Completion m_currentResult; 0113 bool m_bindingsEnabled; 0114 }; 0115 0116 void setup(KJS::ExecState *exec, KJS::JSObject *parent) 0117 { 0118 StaticBinding::publish(exec, parent, IoFactory::methods()); // Global methods 0119 StaticBinding::publish(exec, parent, FileDialog::methods()); // Global methods 0120 StaticBinding::publish(exec, parent, BuiltinsFactory::methods()); // Global methods 0121 StaticConstructor::add(exec, parent, FileIO::constructor()); // Ctor 0122 StaticConstructor::add(exec, parent, DomNode::constructor()); // Ctor 0123 StaticConstructor::add(exec, parent, DomDocument::constructor()); // Ctor 0124 StaticConstructor::add(exec, parent, DomElement::constructor()); // Ctor 0125 StaticConstructor::add(exec, parent, DomAttr::constructor()); // Ctor 0126 StaticConstructor::add(exec, parent, DomDocumentType::constructor()); // Ctor 0127 StaticConstructor::add(exec, parent, DomNodeList::constructor()); // Ctor 0128 StaticConstructor::add(exec, parent, DomNamedNodeMap::constructor()); // Ctor 0129 StaticConstructor::add(exec, parent, DomText::constructor()); // Ctor 0130 StaticConstructor::add(exec, parent, Url::constructor()); // Ctor 0131 StaticConstructor::add(exec, parent, SettingsBinding::constructor()); // Ctor 0132 StaticConstructor::add(exec, parent, CoreApplicationBinding::constructor()); 0133 StaticConstructor::add(exec, parent, Point::constructor()); // Ctor 0134 StaticConstructor::add(exec, parent, Size::constructor()); // Ctor 0135 StaticConstructor::add(exec, parent, Rect::constructor()); // Ctor 0136 StaticConstructor::add(exec, parent, Color::constructor()); // Ctor 0137 0138 // check if this is a GUI application 0139 QApplication *app = ::qobject_cast<QApplication *>(QCoreApplication::instance()); 0140 if (app) { 0141 //qDebug("Loading GUI Bindings"); 0142 0143 #ifdef KJSEMBED_FORMBUILDER_BINDING 0144 StaticConstructor::add(exec, parent, FormBuilder::constructor()); // Ctor 0145 #endif 0146 StaticConstructor::add(exec, parent, UiLoaderBinding::constructor()); // Ctor 0147 StaticConstructor::add(exec, parent, QWidgetBinding::constructor()); // Ctor 0148 StaticConstructor::add(exec, parent, Layout::constructor()); // Ctor 0149 StaticConstructor::add(exec, parent, Action::constructor()); // Ctor 0150 StaticConstructor::add(exec, parent, ActionGroup::constructor()); // Ctor 0151 StaticConstructor::add(exec, parent, Font::constructor()); // Ctor 0152 StaticConstructor::add(exec, parent, Pen::constructor()); // Ctor 0153 StaticConstructor::add(exec, parent, Brush::constructor()); // Ctor 0154 StaticConstructor::add(exec, parent, Image::constructor()); // Ctor 0155 StaticConstructor::add(exec, parent, Pixmap::constructor()); // Ctor 0156 StaticConstructor::add(exec, parent, Painter::constructor()); // Ctor 0157 StaticConstructor::add(exec, parent, SvgRenderer::constructor()); // Ctor 0158 StaticConstructor::add(exec, parent, SvgWidget::constructor()); // Ctor 0159 StaticConstructor::add(exec, parent, ApplicationBinding::constructor()); 0160 } 0161 } 0162 0163 Engine::Engine(bool enableBindings) 0164 { 0165 dptr = new EnginePrivate(); 0166 if (enableBindings) { 0167 setup(dptr->m_interpreter->globalExec(), dptr->m_interpreter->globalObject()); 0168 } 0169 dptr->m_bindingsEnabled = enableBindings; 0170 } 0171 0172 Engine::~Engine() 0173 { 0174 delete dptr; 0175 } 0176 0177 bool Engine::isBindingsEnabled() const 0178 { 0179 return dptr->m_bindingsEnabled; 0180 } 0181 0182 KJS::JSObject *Engine::addObject(QObject *obj, KJS::JSObject *parent, const KJS::UString &name) const 0183 { 0184 KJS::ExecState *exec = dptr->m_interpreter->globalExec(); 0185 KJS::JSObject *returnObject = KJSEmbed::createQObject(exec, obj, KJSEmbed::ObjectBinding::CPPOwned); 0186 KJS::Identifier jsName(!name.isEmpty() ? name : toUString(obj->objectName())); 0187 0188 parent->putDirect(jsName, returnObject, KJS::DontDelete | KJS::ReadOnly); 0189 return returnObject; 0190 } 0191 0192 KJS::JSObject *Engine::addObject(QObject *obj, const KJS::UString &name) const 0193 { 0194 return addObject(obj, dptr->m_interpreter->globalObject(), name); 0195 } 0196 0197 KJS::Completion Engine::completion() const 0198 { 0199 return dptr->m_currentResult; 0200 } 0201 0202 KJS::Interpreter *Engine::interpreter() const 0203 { 0204 return dptr->m_interpreter; 0205 } 0206 0207 KJS::Completion Engine::runFile(KJS::Interpreter *interpreter, const KJS::UString &fileName) 0208 { 0209 // qDebug() << "runFile: " << toQString(fileName); 0210 KJS::UString code; 0211 QFile file(toQString(fileName)); 0212 if (file.open(QFile::ReadOnly)) { 0213 QTextStream ts(&file); 0214 0215 QString line; 0216 while (!ts.atEnd()) { 0217 line = ts.readLine(); 0218 if (line[0] != '#') { 0219 code += toUString(line + '\n'); 0220 } 0221 } 0222 file.close(); 0223 } else { 0224 code = "println('Could not open file.');"; 0225 qWarning() << "Could not open file " << toQString(fileName); 0226 } 0227 0228 // qDebug() << "Loaded code: " << toQString(code); 0229 0230 return interpreter->evaluate(fileName, 0, code, nullptr); 0231 } 0232 0233 Engine::ExitStatus Engine::runFile(const KJS::UString &fileName) 0234 { 0235 dptr->m_currentResult = runFile(dptr->m_interpreter, fileName); 0236 0237 if (dptr->m_currentResult.complType() == KJS::Normal) { 0238 return Engine::Success; 0239 } else if (dptr->m_currentResult.complType() == KJS::ReturnValue) { 0240 return Engine::Success; 0241 } else { 0242 return Engine::Failure; 0243 } 0244 } 0245 0246 Engine::ExitStatus Engine::execute(const KJS::UString &code) 0247 { 0248 dptr->m_currentResult = dptr->m_interpreter->evaluate(KJS::UString(""), 0, code, nullptr); 0249 if (dptr->m_currentResult.complType() == KJS::Normal) { 0250 return Engine::Success; 0251 } else if (dptr->m_currentResult.complType() == KJS::ReturnValue) { 0252 return Engine::Success; 0253 } else { 0254 return Engine::Failure; 0255 } 0256 } 0257 0258 KJS::JSObject *Engine::construct(const KJS::UString &className, const KJS::List &args) const 0259 { 0260 KJS::JSObject *global = dptr->m_interpreter->globalObject(); 0261 KJS::ExecState *exec = dptr->m_interpreter->globalExec(); 0262 return StaticConstructor::construct(exec, global, className, args); 0263 } 0264 0265 KJS::JSValue *Engine::callMethod(const KJS::UString &methodName, const KJS::List &args) 0266 { 0267 KJS::JSObject *global = dptr->m_interpreter->globalObject(); 0268 KJS::ExecState *exec = dptr->m_interpreter->globalExec(); 0269 0270 KJS::Identifier id = KJS::Identifier(KJS::UString(methodName)); 0271 KJS::JSObject *fun = global->get(exec, id)->toObject(exec); 0272 KJS::JSValue *retValue; 0273 0274 if (!fun->implementsCall()) { 0275 QString msg = i18n("%1 is not a function and cannot be called.", toQString(methodName)); 0276 return throwError(exec, KJS::TypeError, msg); 0277 } 0278 0279 retValue = fun->call(exec, global, args); 0280 0281 if (exec->hadException()) { 0282 return exec->exception(); 0283 } 0284 0285 return retValue; 0286 } 0287 0288 KJS::JSValue *Engine::callMethod(KJS::JSObject *parent, 0289 const KJS::UString &methodName, const KJS::List &args) 0290 { 0291 KJS::ExecState *exec = dptr->m_interpreter->globalExec(); 0292 0293 KJS::Identifier id = KJS::Identifier(methodName); 0294 KJS::JSObject *fun = parent->get(exec, id)->toObject(exec); 0295 KJS::JSValue *retValue; 0296 0297 if (!fun->implementsCall()) { 0298 QString msg = i18n("%1 is not a function and cannot be called.", toQString(methodName)); 0299 return throwError(exec, KJS::TypeError, msg); 0300 } 0301 0302 retValue = fun->call(exec, parent, args); 0303 0304 if (exec->hadException()) { 0305 return exec->exception(); 0306 } 0307 0308 return retValue; 0309 } 0310 0311 } // namespace KJS 0312