/*
 * Copyright (c) 2015 Canon 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 "ReadableStreamDefaultReaderBuiltins.h"

#if ENABLE(READABLE_STREAM_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_readableStreamDefaultReaderCancelCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_readableStreamDefaultReaderCancelCodeLength = 396;
static const JSC::Intrinsic s_readableStreamDefaultReaderCancelCodeIntrinsic = JSC::NoIntrinsic;
const char* s_readableStreamDefaultReaderCancelCode =
    "(function (reason)\n" \
    "{\n" \
    "    \"use strict\";\n" \
    "    if (!@isReadableStreamDefaultReader(this))\n" \
    "        return @Promise.@reject(@makeThisTypeError(\"ReadableStreamDefaultReader\", \"cancel\"));\n" \
    "    if (!this.@ownerReadableStream)\n" \
    "        return @Promise.@reject(new @TypeError(\"cancel() called on a reader owned by no readable stream\"));\n" \
    "    return @cancelReadableStream(this.@ownerReadableStream, reason);\n" \
    "})\n" \
;

const JSC::ConstructAbility s_readableStreamDefaultReaderReadCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_readableStreamDefaultReaderReadCodeLength = 372;
static const JSC::Intrinsic s_readableStreamDefaultReaderReadCodeIntrinsic = JSC::NoIntrinsic;
const char* s_readableStreamDefaultReaderReadCode =
    "(function ()\n" \
    "{\n" \
    "    \"use strict\";\n" \
    "    if (!@isReadableStreamDefaultReader(this))\n" \
    "        return @Promise.@reject(@makeThisTypeError(\"ReadableStreamDefaultReader\", \"read\"));\n" \
    "    if (!this.@ownerReadableStream)\n" \
    "        return @Promise.@reject(new @TypeError(\"read() called on a reader owned by no readable stream\"));\n" \
    "    return @readFromReadableStreamDefaultReader(this);\n" \
    "})\n" \
;

const JSC::ConstructAbility s_readableStreamDefaultReaderReleaseLockCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_readableStreamDefaultReaderReleaseLockCodeLength = 758;
static const JSC::Intrinsic s_readableStreamDefaultReaderReleaseLockCodeIntrinsic = JSC::NoIntrinsic;
const char* s_readableStreamDefaultReaderReleaseLockCode =
    "(function ()\n" \
    "{\n" \
    "    \"use strict\";\n" \
    "    if (!@isReadableStreamDefaultReader(this))\n" \
    "        throw @makeThisTypeError(\"ReadableStreamDefaultReader\", \"releaseLock\");\n" \
    "    const stream = this.@ownerReadableStream;\n" \
    "    if (!stream)\n" \
    "         return;\n" \
    "    if (this.@readRequests.length)\n" \
    "        throw new @TypeError(\"There are still pending read requests, cannot release the lock\");\n" \
    "    if (stream.@state === @streamReadable)\n" \
    "        this.@closedPromiseCapability.@reject.@call(@undefined, new @TypeError(\"releasing lock of reader whose stream is still in readable state\"));\n" \
    "    else\n" \
    "        this.@closedPromiseCapability = { @promise: @Promise.@reject(new @TypeError(\"reader released lock\")) };\n" \
    "    stream.@reader = @undefined;\n" \
    "    this.@ownerReadableStream = null;\n" \
    "})\n" \
;

const JSC::ConstructAbility s_readableStreamDefaultReaderClosedCodeConstructAbility = JSC::ConstructAbility::CannotConstruct;
const int s_readableStreamDefaultReaderClosedCodeLength = 230;
static const JSC::Intrinsic s_readableStreamDefaultReaderClosedCodeIntrinsic = JSC::NoIntrinsic;
const char* s_readableStreamDefaultReaderClosedCode =
    "(function ()\n" \
    "{\n" \
    "    \"use strict\";\n" \
    "    if (!@isReadableStreamDefaultReader(this))\n" \
    "        return @Promise.@reject(@makeGetterTypeError(\"ReadableStreamDefaultReader\", \"closed\"));\n" \
    "    return this.@closedPromiseCapability.@promise;\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().readableStreamDefaultReaderBuiltins().codeName##Executable()->link(vm, clientData->builtinFunctions().readableStreamDefaultReaderBuiltins().codeName##Source(), Nullopt, s_##codeName##Intrinsic); \
}
WEBCORE_FOREACH_READABLESTREAMDEFAULTREADER_BUILTIN_CODE(DEFINE_BUILTIN_GENERATOR)
#undef DEFINE_BUILTIN_GENERATOR


} // namespace WebCore

#endif // ENABLE(READABLE_STREAM_API)
