/*
 * Copyright (c) 2016 Apple Inc.
 * Copyright (c) 2016 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 INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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.
 * 
 */

// DO NOT EDIT THIS FILE. It is automatically generated from JavaScript files for
// builtins by the script: Source/JavaScriptCore/Scripts/generate-js-builtins.py

#include "config.h"
#include "FetchInternalsBuiltins.h"

#if ENABLE(FETCH_API)

#include "WebCoreJSClientData.h"
#include <heap/HeapInlines.h>
#include <runtime/Executable.h>
#include <runtime/Intrinsic.h>
#include <runtime/JSCJSValueInlines.h>
#include <runtime/JSCellInlines.h>
#include <runtime/StructureInlines.h>
#include <runtime/VM.h>

namespace WebCore {

const JSC::ConstructAbility s_fetchInternalsFillFetchHeadersCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_fetchInternalsFillFetchHeadersCodeLength = 814;
static const JSC::Intrinsic s_fetchInternalsFillFetchHeadersCodeIntrinsic = JSC::NoIntrinsic;
const char* s_fetchInternalsFillFetchHeadersCode =
    "(function (headers, headersInit)\n" \
    "{\n" \
    "    \"use strict\";\n" \
    "    if (headersInit instanceof @Headers) {\n" \
    "        @Headers.prototype.@fillFromJS.@call(headers, headersInit);\n" \
    "        return;\n" \
    "    }\n" \
    "    if (@isArray(headersInit)) {\n" \
    "        for (let i = 0; i < headersInit.length; i++) {\n" \
    "            let header = headersInit[i];\n" \
    "            if (header.length !== 2)\n" \
    "                throw new @TypeError(\"headersInit sequence items should contain two values\");\n" \
    "            @Headers.prototype.@appendFromJS.@call(headers, header[0], header[1]);\n" \
    "        }\n" \
    "        return this;\n" \
    "    }\n" \
    "    let propertyNames = @Object.@getOwnPropertyNames(headersInit);\n" \
    "    for (let i = 0; i < propertyNames.length; ++i) {\n" \
    "        let name = propertyNames[i];\n" \
    "        @Headers.prototype.@appendFromJS.@call(headers, name, headersInit[name]);\n" \
    "    }\n" \
    "})\n" \
;

const JSC::ConstructAbility s_fetchInternalsConsumeStreamCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_fetchInternalsConsumeStreamCodeLength = 939;
static const JSC::Intrinsic s_fetchInternalsConsumeStreamCodeIntrinsic = JSC::NoIntrinsic;
const char* s_fetchInternalsConsumeStreamCode =
    "(function (response, type)\n" \
    "{\n" \
    "    @assert(response instanceof @Response);\n" \
    "    @assert(response.@body instanceof @ReadableStream);\n" \
    "    if (@isReadableStreamDisturbed(response.@body))\n" \
    "        return @Promise.@reject(new @TypeError(\"Cannot consume a disturbed Response body ReadableStream\"));\n" \
    "    try {\n" \
    "        let reader = new @ReadableStreamDefaultReader(response.@body);\n" \
    "        @Response.prototype.@startConsumingStream.@call(response, type);\n" \
    "        let pull = (result) => {\n" \
    "            if (result.done)\n" \
    "                return @Response.prototype.@finishConsumingStream.@call(response);\n" \
    "            @Response.prototype.@consumeChunk.@call(response, result.value);\n" \
    "            return @Promise.prototype.@then.@call(@readFromReadableStreamDefaultReader(reader), pull);\n" \
    "        }\n" \
    "        return @Promise.prototype.@then.@call(@readFromReadableStreamDefaultReader(reader), pull);\n" \
    "    } catch(e) {\n" \
    "        return @Promise.@reject(e);\n" \
    "    }\n" \
    "})\n" \
;


#define DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \
JSC::FunctionExecutable* codeName##Generator(JSC::VM& vm) \
{\
    JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData); \
    return clientData->builtinFunctions().fetchInternalsBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().fetchInternalsBuiltins().codeName##Source(), Nullopt, s_##codeName##Intrinsic); \
}
WEBCORE_FOREACH_FETCHINTERNALS_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
#undef DEFINE_BUILTIN_GENERATOR


} // namespace WebCore

#endif // ENABLE(FETCH_API)
