webengine/device/src/DeviceLiwIterable.cpp
changeset 0 dd21522fd290
child 10 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation of LIW Iterable wrapper
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include <config.h>
       
    21 #include <lookup.h>
       
    22 #include <LiwServiceHandler.h>
       
    23 #include "DeviceLiwIterable.h"
       
    24 #include "DeviceLiwBinding.h"
       
    25 
       
    26 const TInt KMaxKeySize = 128;
       
    27 
       
    28 using namespace KJS;
       
    29 
       
    30 const ClassInfo DeviceLiwIterable::info = { "DeviceLiwIterable", 0, 0, 0 };
       
    31 const TInt INIT_JSOBJ_ARRAY_SIZE = 10;   // initial jsobject array
       
    32 // ============================= LOCAL FUNCTIONS ===============================
       
    33 /*
       
    34 @begin DeviceLiwIterableTable 1
       
    35     getNext DeviceLiwIterable::getNext DontDelete|Function 0
       
    36     reset   DeviceLiwIterable::reset   DontDelete|Function 0
       
    37     close   DeviceLiwIterable::close   DontDelete|Function 0
       
    38 @end
       
    39 */
       
    40 
       
    41 /*
       
    42  * The DeviceLiwIterable is a plain wrapper around the underlying LIW iterable variant
       
    43  * object. It acts as a pass through for the iterable methods to JS. This
       
    44  * is needed for efficiently processing returned iterables (instead of copying the
       
    45  * contents into a JS array). Of course much of the benefit depends on how well iterables
       
    46  * are implemented in the underlying LIW framework.
       
    47  */
       
    48 
       
    49 // ============================ MEMBER FUNCTIONS ===============================
       
    50 
       
    51 
       
    52 // ----------------------------------------------------------------------------
       
    53 // DeviceLiwIterable::DeviceLiwIterable
       
    54 //
       
    55 // ----------------------------------------------------------------------------
       
    56 //
       
    57 DeviceLiwIterable::DeviceLiwIterable(
       
    58     ExecState* exec,
       
    59     CDeviceLiwBinding* binding,
       
    60     CLiwIterable* variant)
       
    61     : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype() )
       
    62     {
       
    63         m_privateData = new DeviceLiwIterablePrivate(variant, binding);
       
    64         if (!m_privateData || !m_privateData->m_jsobjArray )
       
    65             m_valid = false;
       
    66         else 
       
    67             {
       
    68             m_valid = true;
       
    69             KJS::Collector::protect(this);            
       
    70             }            
       
    71     }
       
    72 
       
    73 // ----------------------------------------------------------------------------
       
    74 // DeviceLiwIterable::~DeviceLiwIterable
       
    75 //
       
    76 // ----------------------------------------------------------------------------
       
    77 //
       
    78 DeviceLiwIterable::~DeviceLiwIterable()
       
    79     {
       
    80         // only can be called by garbage collection after the 
       
    81         // DeviceLiwIterable::Close() was called
       
    82     }
       
    83 
       
    84 // ----------------------------------------------------------------------------
       
    85 // DeviceLiwIterable::Close()
       
    86 //
       
    87 // ----------------------------------------------------------------------------
       
    88 //
       
    89 void DeviceLiwIterable::Close(ExecState* exec, bool unmark)
       
    90     {
       
    91     // avoid double close    
       
    92     if(!m_valid) 
       
    93         {   
       
    94         if(unmark) 
       
    95             {
       
    96             // unprotect this to allow the garbage collection to release this jsobject
       
    97             KJS::Collector::unprotect(this);
       
    98             }
       
    99         return;
       
   100         }
       
   101     
       
   102     // need exec to close other jsobject
       
   103     m_privateData->m_exec = exec;
       
   104     delete m_privateData;
       
   105     m_privateData = NULL;
       
   106     m_valid = false;
       
   107     
       
   108     if(unmark) 
       
   109         {
       
   110         // unprotect this to allow the garbage collection to release this jsobject
       
   111         KJS::Collector::unprotect(this);
       
   112         }
       
   113     }     
       
   114 
       
   115 // ----------------------------------------------------------------------------
       
   116 // DeviceLiwIterable::toString
       
   117 // Returns string representation of the object
       
   118 //
       
   119 // ----------------------------------------------------------------------------
       
   120 UString DeviceLiwIterable::toString(ExecState* /*exec*/) const
       
   121     {
       
   122     return "[object DeviceLiwIterable]";
       
   123     }
       
   124 
       
   125 // ----------------------------------------------------------------------------
       
   126 // Device::getOwnPropertySlot
       
   127 //
       
   128 // ----------------------------------------------------------------------------
       
   129 
       
   130 bool DeviceLiwIterable::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
       
   131     {
       
   132     // When the DeviceLiwIterable is valid, the check order is
       
   133     //      DeviceLiwIterable table => own property => prototype property
       
   134     // When the DeviceLiwIterable is invalid (after close), the check order is
       
   135     //      close function in table => prototype property
       
   136 
       
   137     // 1. when it is valid
       
   138     if(m_valid) 
       
   139         {
       
   140         // 1.1 check DeviceLiwIterable table    
       
   141         const HashEntry* entry = Lookup::findEntry(&DeviceLiwIterableTable, propertyName);
       
   142         if (entry)
       
   143             {
       
   144             slot.setStaticEntry(this, entry, staticValueGetter<DeviceLiwIterable>);
       
   145             return true;
       
   146             }
       
   147 
       
   148         // 1.2 check own property
       
   149         if(JSObject::getOwnPropertySlot(exec, propertyName, slot))
       
   150             return true;
       
   151         
       
   152         // 1.3 check prototypes
       
   153         JSObject *proto = static_cast<JSObject *>(this->prototype());
       
   154         while (!proto->isNull() && proto->isObject())
       
   155             {
       
   156             if (proto->getOwnPropertySlot(exec, propertyName, slot))
       
   157                 return true;
       
   158 
       
   159             proto = static_cast<JSObject *>(proto->prototype());
       
   160             }
       
   161         }
       
   162     // 2. when it is invalid
       
   163     else
       
   164         {
       
   165         // 2.1 check close() function
       
   166         if (propertyName == "close")
       
   167             {
       
   168             const HashEntry* entry = Lookup::findEntry(&DeviceLiwIterableTable, propertyName);
       
   169             if (entry)
       
   170                 {
       
   171                 slot.setStaticEntry(this, entry, staticValueGetter<DeviceLiwIterable>);
       
   172                 return true;
       
   173                 }      
       
   174             }
       
   175 
       
   176         // 2.2 check prototypes
       
   177         JSObject *proto = static_cast<JSObject *>(this->prototype());
       
   178         while (!proto->isNull() && proto->isObject())
       
   179             {
       
   180             if (proto->getOwnPropertySlot(exec, propertyName, slot))
       
   181                 return true;
       
   182 
       
   183             proto = static_cast<JSObject *>(proto->prototype());
       
   184             }
       
   185         }
       
   186 
       
   187     return false;
       
   188     }
       
   189 
       
   190 // ----------------------------------------------------------------------------
       
   191 // JSVersion::getValueProperty
       
   192 //
       
   193 // ----------------------------------------------------------------------------
       
   194 JSValue* DeviceLiwIterable::getValueProperty(ExecState *exec, int token) const
       
   195     {
       
   196     DeviceLiwIterableFunc *lf;
       
   197     switch (token)
       
   198             {
       
   199             // Unfortunately, the only operations that LIW Iterables support are next() and reset(). e.g. there
       
   200             // are no hasNext() or count() operations typical for iterators.
       
   201             case getNext:
       
   202             case reset:
       
   203             case close:
       
   204                 {
       
   205                 lf = new DeviceLiwIterableFunc(exec, token);
       
   206                 break;
       
   207                 }
       
   208 
       
   209             default:
       
   210                 return throwError(exec, GeneralError);
       
   211             }
       
   212             return lf;
       
   213     }
       
   214     
       
   215 // ---------------------------------------------------------------------------
       
   216 // DeviceLiwIterablePrivate constructor
       
   217 //
       
   218 // ---------------------------------------------------------------------------
       
   219 DeviceLiwIterablePrivate::DeviceLiwIterablePrivate(const CLiwIterable* liwIterable, CDeviceLiwBinding* liwBinding)
       
   220     {
       
   221     TRAP_IGNORE(
       
   222             m_liwBinding = liwBinding;
       
   223             m_jsobjArray = new RPointerArray<JSObject>( INIT_JSOBJ_ARRAY_SIZE );
       
   224             m_exec = NULL;    
       
   225             m_iterable = (CLiwIterable*) liwIterable;
       
   226             if ( m_iterable )
       
   227                 m_iterable->IncRef();
       
   228             )
       
   229     }
       
   230     
       
   231 // ---------------------------------------------------------------------------
       
   232 // DeviceLiwMapPrivate::Close
       
   233 //
       
   234 // ---------------------------------------------------------------------------
       
   235 void DeviceLiwIterablePrivate::Close()
       
   236     {
       
   237     // close the jsobject
       
   238     if ( m_jsobjArray && m_exec )
       
   239         {
       
   240         // close all the DeviceLiwMap objects and DeviceLiwIterable objects
       
   241         for (int i = 0; i < m_jsobjArray->Count(); i++)
       
   242             {
       
   243             JSObject * jsobj = (*m_jsobjArray)[i];
       
   244             if (jsobj->inherits( &DeviceLiwIterable::info ))
       
   245                 {
       
   246                 (static_cast<DeviceLiwIterable*>(jsobj))->Close(m_exec, true);
       
   247                 }
       
   248             else if (jsobj->inherits( &DeviceLiwMap::info ))
       
   249                 {
       
   250                 (static_cast<DeviceLiwMap*>(jsobj))->Close(m_exec, true);
       
   251                 }
       
   252             }
       
   253         m_jsobjArray->Close();
       
   254         delete m_jsobjArray;
       
   255         m_jsobjArray = NULL;
       
   256         m_exec = NULL;
       
   257         }
       
   258     
       
   259     // release the map    
       
   260     if ( m_iterable ) 
       
   261         {
       
   262         m_iterable->DecRef();
       
   263         m_iterable = NULL;
       
   264         }        
       
   265     }
       
   266     
       
   267 // ----------------------------------------------------------------------------
       
   268 // DeviceLiwIterablePrivate::DeviceLiwIterableFunc
       
   269 //
       
   270 // ----------------------------------------------------------------------------
       
   271 //
       
   272 DeviceLiwIterableFunc::DeviceLiwIterableFunc( ExecState* exec, int token )
       
   273     : JSObject( exec->lexicalInterpreter()->builtinObjectPrototype() ),
       
   274     m_func( token )
       
   275     {
       
   276     }
       
   277 
       
   278 // ----------------------------------------------------------------------------
       
   279 // DeviceLiwIterableFunc::~DeviceLiwIterableFunc
       
   280 //
       
   281 // ----------------------------------------------------------------------------
       
   282 //
       
   283 DeviceLiwIterableFunc::~DeviceLiwIterableFunc()
       
   284     {
       
   285     }
       
   286 
       
   287 // ----------------------------------------------------------------------------
       
   288 // DeviceLiwIterableFunc::implementsCall
       
   289 //
       
   290 // ----------------------------------------------------------------------------
       
   291 //
       
   292 bool DeviceLiwIterableFunc::implementsCall() const
       
   293     {
       
   294     return true;
       
   295     }
       
   296 
       
   297 // ----------------------------------------------------------------------------
       
   298 // DeviceLiwIterableFunc::callAsFunction
       
   299 //
       
   300 // ----------------------------------------------------------------------------
       
   301 //
       
   302 JSValue* DeviceLiwIterableFunc::callAsFunction(ExecState* exec, JSObject *thisObj, const List& aArgs )
       
   303     {
       
   304         JSValue* rval = jsUndefined();
       
   305         TBool found = EFalse;
       
   306 
       
   307         if (!thisObj->inherits(&DeviceLiwIterable::info)) {
       
   308                     return throwError(exec, GeneralError);
       
   309         }
       
   310 
       
   311         DeviceLiwIterable *it = static_cast<DeviceLiwIterable *>(thisObj);
       
   312         
       
   313         if ( !it->isValid() || !it->m_privateData->m_liwBinding || !it->m_privateData->m_iterable) {
       
   314             return rval;
       
   315         }
       
   316 
       
   317         if ( m_func == DeviceLiwIterable::getNext ) {
       
   318             TLiwVariant vv;
       
   319             TRAP_IGNORE( found = it->m_privateData->m_iterable->NextL( vv ) );
       
   320             if( found ) 
       
   321                 {
       
   322                 rval =  it->m_privateData->m_liwBinding->LiwVariant2JsVal( exec, vv );
       
   323                 if(rval->isObject()) 
       
   324                     {
       
   325                     JSObject* obj =  static_cast<JSObject*> (rval);
       
   326                     if(obj->inherits( &KJS::DeviceLiwIterable::info ) || obj->inherits( &KJS::DeviceLiwMap::info ))
       
   327                         {
       
   328                         // insert into jsobject array
       
   329                         it->m_privateData->m_jsobjArray->Append(obj);
       
   330                         }
       
   331                     }                
       
   332                 
       
   333                 vv.Reset();
       
   334                 }
       
   335         }
       
   336         else if ( m_func == DeviceLiwIterable::reset ){
       
   337             it->m_privateData->m_iterable->Reset();
       
   338         }
       
   339         else if ( m_func == DeviceLiwIterable::close ){
       
   340             it->Close(exec, false);
       
   341         }
       
   342         return rval;
       
   343     }
       
   344 //END OF FILE
       
   345 
       
   346 
       
   347