/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 *
 */

module threads {

    interface [
        Conditional=WORKERS,
        JSCustomMarkFunction,
        JSCustomGetOwnPropertySlotAndDescriptor,
        EventTarget,
        ExtendsDOMGlobalObject,
        IsWorkerContext,
        JSLegacyParent=JSWorkerContextBase,
        JSNoStaticTables,
        OmitConstructor,
        V8CustomToJSObject
    ] WorkerContext {

        // WorkerGlobalScope
#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
                 attribute [Replaceable] WorkerContext self;
#endif
                 attribute [Replaceable] WorkerLocation location;
        void close();
                 attribute EventListener onerror;

        // WorkerUtils
        [Custom] void importScripts(/*[Variadic] in DOMString urls */);
                 attribute [Replaceable] WorkerNavigator navigator;

        // Timers
        [Custom] long setTimeout(in TimeoutHandler handler, in long timeout);
        // [Custom] long setTimeout(in DOMString code, in long timeout);
        void clearTimeout(in [Optional=DefaultIsUndefined] long handle);
        [Custom] long setInterval(in TimeoutHandler handler, in long timeout);
        // [Custom] long setInterval(in DOMString code, in long timeout);
        void clearInterval(in [Optional=DefaultIsUndefined] long handle);


        // EventTarget interface
        void addEventListener(in DOMString type, 
                              in EventListener listener, 
                              in [Optional] boolean useCapture);
        void removeEventListener(in DOMString type, 
                                 in EventListener listener, 
                                 in [Optional] boolean useCapture);
        boolean dispatchEvent(in Event evt)
            raises(EventException);

#if !defined(LANGUAGE_CPP) || !LANGUAGE_CPP
        // Constructors
        attribute MessageEventConstructor MessageEvent;
        attribute WorkerLocationConstructor WorkerLocation;

#if ENABLE_CHANNEL_MESSAGING
        attribute [JSCustomGetter] MessageChannelConstructor MessageChannel;
#endif
        attribute [JSCustomGetter] EventSourceConstructor EventSource;
        attribute [JSCustomGetter] XMLHttpRequestConstructor XMLHttpRequest;
#endif

#if defined(ENABLE_BLOB) && ENABLE_BLOB
        attribute [Conditional=LEGACY_WEBKIT_BLOB_BUILDER] WebKitBlobBuilderConstructor WebKitBlobBuilder;
        attribute BlobConstructor Blob;
        attribute FileReaderConstructor FileReader;
        attribute FileReaderSyncConstructor FileReaderSync;
#endif

        attribute [Conditional=BLOB] DOMURLConstructor webkitURL;

        attribute ArrayBufferConstructor ArrayBuffer; // Usable with new operator
        attribute Int8ArrayConstructor Int8Array; // Usable with new operator
        attribute Uint8ArrayConstructor Uint8Array; // Usable with new operator
        attribute Uint8ArrayConstructor Uint8ClampedArray; // Usable with new operator
        attribute Int16ArrayConstructor Int16Array; // Usable with new operator
        attribute Uint16ArrayConstructor Uint16Array; // Usable with new operator
        attribute Int32ArrayConstructor Int32Array; // Usable with new operator
        attribute Uint32ArrayConstructor Uint32Array; // Usable with new operator
        attribute Float32ArrayConstructor Float32Array; // Usable with new operator
        attribute Float64ArrayConstructor Float64Array; // Usable with new operator
        attribute DataViewConstructor DataView; // Usable with new operator
    };

}
