void HTTPClientBinding::Open(const ValueList& args, SharedValue result) { if (args.size()<2) { throw ValueException::FromString("invalid arguments"); } this->method = args.at(0)->ToString(); this->url = args.at(1)->ToString(); if (args.size()>=3) { GET_BOOL_PROP(args.at(2),this->async) } if (args.size()>=4) { this->user = args.at(3)->ToString(); } if (args.size()>4) { this->password = args.at(4)->ToString(); } // assign it here (helps prevent deadlock) SharedValue v = this->Get("onreadystatechange"); if (v->IsMethod()) { this->readystate = v->ToMethod(); } SharedValue vc = this->Get("onchange"); if (vc->IsMethod()) { this->onchange = vc->ToMethod(); } this->ChangeState(1); // opened }
HRESULT STDMETHODCALLTYPE ScriptEvaluator::evaluate(BSTR mimeType, BSTR sourceCode, int *context) { std::string type = BSTRToString(mimeType); std::string moduleName = GetModuleName(type); JSContextRef contextRef = reinterpret_cast<JSContextRef>(context); SharedKObject global = host->GetGlobalObject(); SharedValue moduleValue = global->Get(moduleName.c_str()); if (!moduleValue->IsNull()) { SharedValue evalValue = moduleValue->ToObject()->Get("evaluate"); if (!evalValue->IsNull() && evalValue->IsMethod()) { ValueList args; SharedValue typeValue = Value::NewString(type); SharedValue sourceCodeValue = Value::NewString(BSTRToString(sourceCode)); JSObjectRef globalObjectRef = JSContextGetGlobalObject(contextRef); SharedKObject contextObject = new KKJSObject(contextRef, globalObjectRef); SharedValue contextValue = Value::NewObject(contextObject); args.push_back(typeValue); args.push_back(sourceCodeValue); args.push_back(contextValue); evalValue->ToMethod()->Call(args); } } return S_OK; }
void WorkerContext::SendQueuedMessages() { Logger *logger = Logger::Get("WorkerContext"); logger->Debug("SendQueuedMessages called"); SharedValue onmessage = worker->Get("onmessage"); Poco::ScopedLock<Poco::Mutex> lock(mutex); if (onmessage->IsMethod()) { if (messages.size()>0) { std::list<SharedValue>::iterator i = messages.begin(); while(i!=messages.end()) { SharedValue v = (*i++); ValueList _args; string name = "worker.message"; AutoPtr<KEventObject> target = this; this->duplicate(); AutoPtr<Event> event = new Event(target, name); event->Set("message", v); _args.push_back(Value::NewObject(event)); host->InvokeMethodOnMainThread(onmessage->ToMethod(),_args,false); } messages.clear(); } } }
SharedKMethod KObject::GetMethod(const char* name, SharedKMethod defaultValue) { SharedValue prop = this->Get(name); if (prop->IsMethod()) { return prop->ToMethod(); } else { return defaultValue; } }
bool KKJSList::Remove(unsigned int index) { if (index >= 0 && index < this->Size()) { SharedValue spliceMethod = this->kjs_bound_object->Get("splice"); spliceMethod->ToMethod()->Call( Value::NewInt(index), Value::NewInt(1)); return true; } return false; }
void Win32Process::InvokeOnExit() { SharedValue sv = this->Get("onexit"); if (!sv->IsMethod()) { return; } ValueList args(Value::NewInt(this->exitCode)); SharedKMethod callback = sv->ToMethod(); this->parent->GetHost()->InvokeMethodOnMainThread( callback, args, false); }
SharedValue AccessorBoundList::Get(const char *name) { std::string getter_name = "get" + Capitalize(name); SharedValue v = this->RawGet(getter_name.c_str()); if (v->IsMethod()) { SharedKMethod m = v->ToMethod(); return m->Call(ValueList()); } else { return this->RawGet(name); } }
// this method creates the native menu objects for *this* menu item Win32MenuItemImpl::NativeMenuItem* Win32MenuItemImpl::MakeNativeMenuItem(NativeMenuItem* parent_menu_item, bool is_menu_bar) { NativeMenuItem* menu_item = new NativeMenuItem(); if(parent_menu_item) { menu_item->parent_menu = parent_menu_item->menu; } const char* label = this->GetLabel(); const char* iconUrl = this->GetIconURL(); SharedString iconPath = UIModule::GetResourcePath(iconUrl); SharedValue callbackVal = this->RawGet("callback"); if (this->parent == NULL) // top-level { if (is_menu_bar) menu_item->menu = CreateMenu(); else menu_item->menu = CreatePopupMenu(); } else if(this->IsSeparator()) { AppendMenu(menu_item->parent_menu, MF_SEPARATOR, 1, "Separator"); } else if(this->IsItem()) { menu_item->menuItemID = nextMenuUID(); AppendMenu(menu_item->parent_menu, MF_STRING, menu_item->menuItemID, (LPCTSTR) label); if (callbackVal->IsMethod()) { menu_item->callback = callbackVal->ToMethod(); itemsWithCallbacks.push_back(menu_item); } } else if(this->IsSubMenu()) { menu_item->menu = CreatePopupMenu(); AppendMenu(menu_item->parent_menu, MF_STRING | MF_POPUP, (UINT_PTR) menu_item->menu, (LPCTSTR) label); } else { throw ValueException::FromString("Unknown menu item type requested"); } return menu_item; }
// A :method_missing method for finding KObject properties in Ruby static VALUE RubyKObjectMethodMissing(int argc, VALUE *argv, VALUE self) { SharedValue* dval = NULL; Data_Get_Struct(self, SharedValue, dval); SharedKObject object = (*dval)->ToObject(); // TODO: We should raise an exception instead if (object.isNull()) return Qnil; // This is the same error that ruby throws if (argc == 0 || !SYMBOL_P(argv[0])) { rb_raise(rb_eArgError, "no id given"); } // We need to determine the method that was invoked: // store the method name and arguments in separate variables VALUE r_name, args; rb_scan_args(argc, argv, "1*", &r_name, &args); const char* name = rb_id2name(SYM2ID(r_name)); // Check if this is an assignment SharedValue value = object->Get(name); if (name[strlen(name) - 1] == '=' && argc > 1) { char* mod_name = strdup(name); mod_name[strlen(mod_name) - 1] = '\0'; value = RubyUtils::ToKrollValue(argv[1]); object->Set(mod_name, value); free(mod_name); return argv[1]; } else if (value->IsUndefined()) // raise a method missing error { VALUE selfString = rb_obj_as_string(self); rb_raise(rb_eNoMethodError, "undefined method `%s' for %s", name, RubyUtils::ToString(selfString)); } else if (value->IsMethod()) // actually call a method { return RubyUtils::GenericKMethodCall(value->ToMethod(), args); } else // Plain old access { return RubyUtils::ToRubyValue(value); } }
VALUE RubyUtils::ToRubyValue(SharedValue value) { if (value->IsNull() || value->IsUndefined()) { return Qnil; } if (value->IsBool()) { return value->ToBool() ? Qtrue : Qfalse; } else if (value->IsNumber()) { return rb_float_new(value->ToNumber()); } else if (value->IsString()) { return rb_str_new2(value->ToString()); } else if (value->IsObject()) { AutoPtr<KRubyObject> ro = value->ToObject().cast<KRubyObject>(); if (!ro.isNull()) return ro->ToRuby(); AutoPtr<KRubyHash> rh = value->ToObject().cast<KRubyHash>(); if (!rh.isNull()) return rh->ToRuby(); return RubyUtils::KObjectToRubyValue(value); } else if (value->IsMethod()) { AutoPtr<KRubyMethod> rm = value->ToMethod().cast<KRubyMethod>(); if (!rm.isNull()) return rm->ToRuby(); else return RubyUtils::KMethodToRubyValue(value); } else if (value->IsList()) { AutoPtr<KRubyList> rl = value->ToList().cast<KRubyList>(); if (!rl.isNull()) return rl->ToRuby(); else return RubyUtils::KListToRubyValue(value); } return Qnil; }
void AccessorBoundList::Set(const char *name, SharedValue value) { std::string setter_name = "set" + Capitalize(name); SharedValue v = this->RawGet(setter_name.c_str()); if (v->IsMethod()) { SharedKMethod m = v->ToMethod(); ValueList args; args.push_back(value); m->Call(args); } else { this->RawSet(name, value); } }
void Win32Process::InvokeOnRead(std::ostringstream& buffer, bool isErr) { SharedValue sv = this->Get("onread"); if (!sv->IsMethod()) { return; } if (!buffer.str().empty()) { ValueList args( Value::NewString(buffer.str()), Value::NewBool(isErr)); SharedKMethod callback = sv->ToMethod(); this->parent->GetHost()->InvokeMethodOnMainThread( callback, args, false); buffer.str(""); } }
void NetworkBinding::GetHostByAddress(const ValueList& args, SharedValue result) { if (args.at(0)->IsObject()) { SharedKObject obj = args.at(0)->ToObject(); SharedPtr<IPAddressBinding> b = obj.cast<IPAddressBinding>(); if (!b.isNull()) { // in this case, they've passed us an IPAddressBinding // object, which we can just retrieve the ipaddress // instance and resolving using it IPAddress addr(b->GetAddress()->toString()); SharedPtr<HostBinding> binding = new HostBinding(addr); if (binding->IsInvalid()) { throw ValueException::FromString("Could not resolve address"); } result->SetObject(binding); return; } else { SharedValue bo = obj->Get("toString"); if (bo->IsMethod()) { SharedKMethod m = bo->ToMethod(); ValueList args; SharedValue tostr = m->Call(args); this->_GetByHost(tostr->ToString(),result); return; } throw ValueException::FromString("Unknown object passed"); } } else if (args.at(0)->IsString()) { // in this case, they just passed in a string so resolve as // normal this->_GetByHost(args.at(0)->ToString(),result); } }
void Worker::Run() { Logger *logger = Logger::Get("Worker"); bool error = false; JSGlobalContextRef context = NULL; try { // create a new global context this->global_object = KJSUtil::CreateNewGlobalContext(this->host); // bind the worker context properties KJSUtil::BindProperties(global_object,this->context); // evaluate the script context = KJSUtil::GetGlobalContext(global_object); KJSUtil::Evaluate(context, (char*)this->code.c_str()); } catch(std::exception &e) { error = true; logger->Error("Error loading worker. Error = %s", e.what()); SharedValue onerror = this->Get("onerror"); if (onerror->IsMethod()) { SharedKMethod method = onerror->ToMethod(); ValueList args; args.push_back(Value::NewString(e.what())); this->host->InvokeMethodOnMainThread(method,args,false); } } if (!error) { // run this thread and wait for pending messages or to be // woken up to stop for(;;) { bool wait = true; { Poco::ScopedLock<Poco::Mutex> lock(mutex); if (this->messages.size()>0) { wait=false; } } if (wait) { condmutex.lock(); // will unlock in wait condition.wait(condmutex); } // check to see if the worker wants to receive messages - we do this // each time since they could define at any time SharedValue mv = KJSUtil::GetProperty(global_object,"onmessage"); if (mv->IsMethod()) { // we have to make a copy since calling the onmessage could be re-entrant // which would cause the postMessage to deadlock. we hold the lock to // make a copy of the contents of the list and then iterate w/o lock std::list<SharedValue> copy; { // lock inside block only to make copy Poco::ScopedLock<Poco::Mutex> lock(mutex); if (this->messages.size()>0) { std::list<SharedValue>::iterator i = this->messages.begin(); while (i!=this->messages.end()) { SharedValue message = (*i++); copy.push_back(message); } this->messages.clear(); } } if (copy.size()>0) { SharedKMethod onmessage = mv->ToMethod(); std::list<SharedValue>::iterator i = copy.begin(); while(i!=copy.end()) { SharedValue message = (*i++); try { ValueList args; string name = "worker.message"; AutoPtr<KEventObject> target = this; this->duplicate(); AutoPtr<Event> event = new Event(target, name); event->Set("message", message); args.push_back(Value::NewObject(event)); host->InvokeMethodOnMainThread(onmessage,args,false); } catch(std::exception &e) { logger->Error("Error dispatching worker message, exception = %s",e.what()); } } } } if (stopped) break; } } // make sure we unregister our global so we don't leak if (global_object!=NULL) { KJSUtil::UnregisterGlobalContext(global_object); } this->global_object = NULL; this->stopped = true; logger->Debug("exiting Worker thread"); }