Home | History | Annotate | Download | only in v8
      1 /*
      2  * Copyright (C) 2008, 2009 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "bindings/v8/V8Utilities.h"
     33 
     34 #include "V8MessagePort.h"
     35 #include "bindings/v8/ScriptState.h"
     36 #include "bindings/v8/V8AbstractEventListener.h"
     37 #include "bindings/v8/V8Binding.h"
     38 #include "bindings/v8/custom/V8ArrayBufferCustom.h"
     39 #include "core/dom/Document.h"
     40 #include "core/dom/ExceptionCode.h"
     41 #include "core/dom/MessagePort.h"
     42 #include "core/dom/ScriptExecutionContext.h"
     43 #include "core/page/Frame.h"
     44 #include "core/workers/WorkerGlobalScope.h"
     45 #include "wtf/ArrayBuffer.h"
     46 #include "wtf/text/WTFString.h"
     47 #include <v8.h>
     48 
     49 
     50 namespace WebCore {
     51 
     52 // Use an array to hold dependents. It works like a ref-counted scheme.
     53 // A value can be added more than once to the DOM object.
     54 void createHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate)
     55 {
     56     v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex);
     57     if (cache->IsNull() || cache->IsUndefined()) {
     58         cache = v8::Array::New();
     59         object->SetInternalField(cacheIndex, cache);
     60     }
     61 
     62     v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache);
     63     cacheArray->Set(v8::Integer::New(cacheArray->Length(), isolate), value);
     64 }
     65 
     66 bool extractTransferables(v8::Local<v8::Value> value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, v8::Isolate* isolate)
     67 {
     68     if (isUndefinedOrNull(value)) {
     69         ports.resize(0);
     70         arrayBuffers.resize(0);
     71         return true;
     72     }
     73 
     74     uint32_t length = 0;
     75     if (value->IsArray()) {
     76         v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value);
     77         length = array->Length();
     78     } else {
     79         if (toV8Sequence(value, length, isolate).IsEmpty())
     80             return false;
     81     }
     82 
     83     v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value);
     84 
     85     // Validate the passed array of transferrables.
     86     for (unsigned int i = 0; i < length; ++i) {
     87         v8::Local<v8::Value> transferrable = transferrables->Get(i);
     88         // Validation of non-null objects, per HTML5 spec 10.3.3.
     89         if (isUndefinedOrNull(transferrable)) {
     90             setDOMException(DataCloneError, isolate);
     91             return false;
     92         }
     93         // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
     94         if (V8MessagePort::HasInstance(transferrable, isolate, worldType(isolate))) {
     95             RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable));
     96             // Check for duplicate MessagePorts.
     97             if (ports.contains(port)) {
     98                 setDOMException(DataCloneError, isolate);
     99                 return false;
    100             }
    101             ports.append(port.release());
    102         } else if (V8ArrayBuffer::HasInstance(transferrable, isolate, worldType(isolate)))
    103             arrayBuffers.append(V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)));
    104         else {
    105             setDOMException(DataCloneError, isolate);
    106             return false;
    107         }
    108     }
    109     return true;
    110 }
    111 
    112 bool getMessagePortArray(v8::Local<v8::Value> value, MessagePortArray& ports, v8::Isolate* isolate)
    113 {
    114     if (isUndefinedOrNull(value)) {
    115         ports.resize(0);
    116         return true;
    117     }
    118     if (!value->IsArray()) {
    119         throwTypeError(isolate);
    120         return false;
    121     }
    122     bool success = false;
    123     ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, isolate, &success);
    124     return success;
    125 }
    126 
    127 void removeHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate)
    128 {
    129     v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex);
    130     if (!cache->IsArray())
    131         return;
    132     v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache);
    133     for (int i = cacheArray->Length() - 1; i >= 0; --i) {
    134         v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i, isolate));
    135         if (cached->StrictEquals(value)) {
    136             cacheArray->Delete(i);
    137             return;
    138         }
    139     }
    140 }
    141 
    142 void transferHiddenDependency(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate* isolate)
    143 {
    144     if (oldValue) {
    145         V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue);
    146         if (oldListener) {
    147             v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject();
    148             if (!oldListenerObject.IsEmpty())
    149                 removeHiddenDependency(object, oldListenerObject, cacheIndex, isolate);
    150         }
    151     }
    152     if (!newValue->IsNull() && !newValue->IsUndefined())
    153         createHiddenDependency(object, newValue, cacheIndex, isolate);
    154 }
    155 
    156 ScriptExecutionContext* getScriptExecutionContext()
    157 {
    158     if (WorkerScriptController* controller = WorkerScriptController::controllerForContext())
    159         return controller->workerGlobalScope();
    160 
    161     return currentDocument();
    162 }
    163 
    164 } // namespace WebCore
    165