diff -r 000000000000 -r dd21522fd290 webengine/device/src/DeviceLiwIterable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/device/src/DeviceLiwIterable.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,347 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of LIW Iterable wrapper +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include "DeviceLiwIterable.h" +#include "DeviceLiwBinding.h" + +const TInt KMaxKeySize = 128; + +using namespace KJS; + +const ClassInfo DeviceLiwIterable::info = { "DeviceLiwIterable", 0, 0, 0 }; +const TInt INIT_JSOBJ_ARRAY_SIZE = 10; // initial jsobject array +// ============================= LOCAL FUNCTIONS =============================== +/* +@begin DeviceLiwIterableTable 1 + getNext DeviceLiwIterable::getNext DontDelete|Function 0 + reset DeviceLiwIterable::reset DontDelete|Function 0 + close DeviceLiwIterable::close DontDelete|Function 0 +@end +*/ + +/* + * The DeviceLiwIterable is a plain wrapper around the underlying LIW iterable variant + * object. It acts as a pass through for the iterable methods to JS. This + * is needed for efficiently processing returned iterables (instead of copying the + * contents into a JS array). Of course much of the benefit depends on how well iterables + * are implemented in the underlying LIW framework. + */ + +// ============================ MEMBER FUNCTIONS =============================== + + +// ---------------------------------------------------------------------------- +// DeviceLiwIterable::DeviceLiwIterable +// +// ---------------------------------------------------------------------------- +// +DeviceLiwIterable::DeviceLiwIterable( + ExecState* exec, + CDeviceLiwBinding* binding, + CLiwIterable* variant) + : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype() ) + { + m_privateData = new DeviceLiwIterablePrivate(variant, binding); + if (!m_privateData || !m_privateData->m_jsobjArray ) + m_valid = false; + else + { + m_valid = true; + KJS::Collector::protect(this); + } + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterable::~DeviceLiwIterable +// +// ---------------------------------------------------------------------------- +// +DeviceLiwIterable::~DeviceLiwIterable() + { + // only can be called by garbage collection after the + // DeviceLiwIterable::Close() was called + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterable::Close() +// +// ---------------------------------------------------------------------------- +// +void DeviceLiwIterable::Close(ExecState* exec, bool unmark) + { + // avoid double close + if(!m_valid) + { + if(unmark) + { + // unprotect this to allow the garbage collection to release this jsobject + KJS::Collector::unprotect(this); + } + return; + } + + // need exec to close other jsobject + m_privateData->m_exec = exec; + delete m_privateData; + m_privateData = NULL; + m_valid = false; + + if(unmark) + { + // unprotect this to allow the garbage collection to release this jsobject + KJS::Collector::unprotect(this); + } + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterable::toString +// Returns string representation of the object +// +// ---------------------------------------------------------------------------- +UString DeviceLiwIterable::toString(ExecState* /*exec*/) const + { + return "[object DeviceLiwIterable]"; + } + +// ---------------------------------------------------------------------------- +// Device::getOwnPropertySlot +// +// ---------------------------------------------------------------------------- + +bool DeviceLiwIterable::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) + { + // When the DeviceLiwIterable is valid, the check order is + // DeviceLiwIterable table => own property => prototype property + // When the DeviceLiwIterable is invalid (after close), the check order is + // close function in table => prototype property + + // 1. when it is valid + if(m_valid) + { + // 1.1 check DeviceLiwIterable table + const HashEntry* entry = Lookup::findEntry(&DeviceLiwIterableTable, propertyName); + if (entry) + { + slot.setStaticEntry(this, entry, staticValueGetter); + return true; + } + + // 1.2 check own property + if(JSObject::getOwnPropertySlot(exec, propertyName, slot)) + return true; + + // 1.3 check prototypes + JSObject *proto = static_cast(this->prototype()); + while (!proto->isNull() && proto->isObject()) + { + if (proto->getOwnPropertySlot(exec, propertyName, slot)) + return true; + + proto = static_cast(proto->prototype()); + } + } + // 2. when it is invalid + else + { + // 2.1 check close() function + if (propertyName == "close") + { + const HashEntry* entry = Lookup::findEntry(&DeviceLiwIterableTable, propertyName); + if (entry) + { + slot.setStaticEntry(this, entry, staticValueGetter); + return true; + } + } + + // 2.2 check prototypes + JSObject *proto = static_cast(this->prototype()); + while (!proto->isNull() && proto->isObject()) + { + if (proto->getOwnPropertySlot(exec, propertyName, slot)) + return true; + + proto = static_cast(proto->prototype()); + } + } + + return false; + } + +// ---------------------------------------------------------------------------- +// JSVersion::getValueProperty +// +// ---------------------------------------------------------------------------- +JSValue* DeviceLiwIterable::getValueProperty(ExecState *exec, int token) const + { + DeviceLiwIterableFunc *lf; + switch (token) + { + // Unfortunately, the only operations that LIW Iterables support are next() and reset(). e.g. there + // are no hasNext() or count() operations typical for iterators. + case getNext: + case reset: + case close: + { + lf = new DeviceLiwIterableFunc(exec, token); + break; + } + + default: + return throwError(exec, GeneralError); + } + return lf; + } + +// --------------------------------------------------------------------------- +// DeviceLiwIterablePrivate constructor +// +// --------------------------------------------------------------------------- +DeviceLiwIterablePrivate::DeviceLiwIterablePrivate(const CLiwIterable* liwIterable, CDeviceLiwBinding* liwBinding) + { + TRAP_IGNORE( + m_liwBinding = liwBinding; + m_jsobjArray = new RPointerArray( INIT_JSOBJ_ARRAY_SIZE ); + m_exec = NULL; + m_iterable = (CLiwIterable*) liwIterable; + if ( m_iterable ) + m_iterable->IncRef(); + ) + } + +// --------------------------------------------------------------------------- +// DeviceLiwMapPrivate::Close +// +// --------------------------------------------------------------------------- +void DeviceLiwIterablePrivate::Close() + { + // close the jsobject + if ( m_jsobjArray && m_exec ) + { + // close all the DeviceLiwMap objects and DeviceLiwIterable objects + for (int i = 0; i < m_jsobjArray->Count(); i++) + { + JSObject * jsobj = (*m_jsobjArray)[i]; + if (jsobj->inherits( &DeviceLiwIterable::info )) + { + (static_cast(jsobj))->Close(m_exec, true); + } + else if (jsobj->inherits( &DeviceLiwMap::info )) + { + (static_cast(jsobj))->Close(m_exec, true); + } + } + m_jsobjArray->Close(); + delete m_jsobjArray; + m_jsobjArray = NULL; + m_exec = NULL; + } + + // release the map + if ( m_iterable ) + { + m_iterable->DecRef(); + m_iterable = NULL; + } + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterablePrivate::DeviceLiwIterableFunc +// +// ---------------------------------------------------------------------------- +// +DeviceLiwIterableFunc::DeviceLiwIterableFunc( ExecState* exec, int token ) + : JSObject( exec->lexicalInterpreter()->builtinObjectPrototype() ), + m_func( token ) + { + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterableFunc::~DeviceLiwIterableFunc +// +// ---------------------------------------------------------------------------- +// +DeviceLiwIterableFunc::~DeviceLiwIterableFunc() + { + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterableFunc::implementsCall +// +// ---------------------------------------------------------------------------- +// +bool DeviceLiwIterableFunc::implementsCall() const + { + return true; + } + +// ---------------------------------------------------------------------------- +// DeviceLiwIterableFunc::callAsFunction +// +// ---------------------------------------------------------------------------- +// +JSValue* DeviceLiwIterableFunc::callAsFunction(ExecState* exec, JSObject *thisObj, const List& aArgs ) + { + JSValue* rval = jsUndefined(); + TBool found = EFalse; + + if (!thisObj->inherits(&DeviceLiwIterable::info)) { + return throwError(exec, GeneralError); + } + + DeviceLiwIterable *it = static_cast(thisObj); + + if ( !it->isValid() || !it->m_privateData->m_liwBinding || !it->m_privateData->m_iterable) { + return rval; + } + + if ( m_func == DeviceLiwIterable::getNext ) { + TLiwVariant vv; + TRAP_IGNORE( found = it->m_privateData->m_iterable->NextL( vv ) ); + if( found ) + { + rval = it->m_privateData->m_liwBinding->LiwVariant2JsVal( exec, vv ); + if(rval->isObject()) + { + JSObject* obj = static_cast (rval); + if(obj->inherits( &KJS::DeviceLiwIterable::info ) || obj->inherits( &KJS::DeviceLiwMap::info )) + { + // insert into jsobject array + it->m_privateData->m_jsobjArray->Append(obj); + } + } + + vv.Reset(); + } + } + else if ( m_func == DeviceLiwIterable::reset ){ + it->m_privateData->m_iterable->Reset(); + } + else if ( m_func == DeviceLiwIterable::close ){ + it->Close(exec, false); + } + return rval; + } +//END OF FILE + + +