--- /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 <config.h>
+#include <lookup.h>
+#include <LiwServiceHandler.h>
+#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<DeviceLiwIterable>);
+ return true;
+ }
+
+ // 1.2 check own property
+ if(JSObject::getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+
+ // 1.3 check prototypes
+ JSObject *proto = static_cast<JSObject *>(this->prototype());
+ while (!proto->isNull() && proto->isObject())
+ {
+ if (proto->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+
+ proto = static_cast<JSObject *>(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<DeviceLiwIterable>);
+ return true;
+ }
+ }
+
+ // 2.2 check prototypes
+ JSObject *proto = static_cast<JSObject *>(this->prototype());
+ while (!proto->isNull() && proto->isObject())
+ {
+ if (proto->getOwnPropertySlot(exec, propertyName, slot))
+ return true;
+
+ proto = static_cast<JSObject *>(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<JSObject>( 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<DeviceLiwIterable*>(jsobj))->Close(m_exec, true);
+ }
+ else if (jsobj->inherits( &DeviceLiwMap::info ))
+ {
+ (static_cast<DeviceLiwMap*>(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<DeviceLiwIterable *>(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<JSObject*> (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
+
+
+