#ifndef SRC_STREAM_BASE_INL_H_ #define SRC_STREAM_BASE_INL_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "stream_base.h" #include "node.h" #include "env-inl.h" #include "v8.h" namespace node { using v8::AccessorSignature; using v8::External; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; using v8::HandleScope; using v8::Local; using v8::Object; using v8::PropertyAttribute; using v8::PropertyCallbackInfo; using v8::String; using v8::Value; using AsyncHooks = Environment::AsyncHooks; template void StreamBase::AddMethods(Environment* env, Local t, int flags) { HandleScope scope(env->isolate()); enum PropertyAttribute attributes = static_cast( v8::ReadOnly | v8::DontDelete | v8::DontEnum); Local signature = AccessorSignature::New(env->isolate(), t); t->PrototypeTemplate()->SetAccessor(env->fd_string(), GetFD, nullptr, env->as_external(), v8::DEFAULT, attributes, signature); t->PrototypeTemplate()->SetAccessor(env->external_stream_string(), GetExternal, nullptr, env->as_external(), v8::DEFAULT, attributes, signature); t->PrototypeTemplate()->SetAccessor(env->bytes_read_string(), GetBytesRead, nullptr, env->as_external(), v8::DEFAULT, attributes, signature); env->SetProtoMethod(t, "readStart", JSMethod); env->SetProtoMethod(t, "readStop", JSMethod); if ((flags & kFlagNoShutdown) == 0) env->SetProtoMethod(t, "shutdown", JSMethod); if ((flags & kFlagHasWritev) != 0) env->SetProtoMethod(t, "writev", JSMethod); env->SetProtoMethod(t, "writeBuffer", JSMethod); env->SetProtoMethod(t, "writeAsciiString", JSMethod >); env->SetProtoMethod(t, "writeUtf8String", JSMethod >); env->SetProtoMethod(t, "writeUcs2String", JSMethod >); env->SetProtoMethod(t, "writeLatin1String", JSMethod >); } template void StreamBase::GetFD(Local key, const PropertyCallbackInfo& args) { // Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD(). Base* handle; ASSIGN_OR_RETURN_UNWRAP(&handle, args.This(), args.GetReturnValue().Set(UV_EINVAL)); StreamBase* wrap = static_cast(handle); if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL); args.GetReturnValue().Set(wrap->GetFD()); } template void StreamBase::GetBytesRead(Local key, const PropertyCallbackInfo& args) { // The handle instance hasn't been set. So no bytes could have been read. Base* handle; ASSIGN_OR_RETURN_UNWRAP(&handle, args.This(), args.GetReturnValue().Set(0)); StreamBase* wrap = static_cast(handle); // uint64_t -> double. 53bits is enough for all real cases. args.GetReturnValue().Set(static_cast(wrap->bytes_read_)); } template void StreamBase::GetExternal(Local key, const PropertyCallbackInfo& args) { Base* handle; ASSIGN_OR_RETURN_UNWRAP(&handle, args.This()); StreamBase* wrap = static_cast(handle); Local ext = External::New(args.GetIsolate(), wrap); args.GetReturnValue().Set(ext); } template & args)> void StreamBase::JSMethod(const FunctionCallbackInfo& args) { Base* handle; ASSIGN_OR_RETURN_UNWRAP(&handle, args.Holder()); StreamBase* wrap = static_cast(handle); if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL); AsyncHooks::InitScope init_scope(handle->env(), handle->get_async_id()); args.GetReturnValue().Set((wrap->*Method)(args)); } WriteWrap* WriteWrap::New(Environment* env, Local obj, StreamBase* wrap, DoneCb cb, size_t extra) { size_t storage_size = ROUND_UP(sizeof(WriteWrap), kAlignSize) + extra; char* storage = new char[storage_size]; return new(storage) WriteWrap(env, obj, wrap, cb, storage_size); } void WriteWrap::Dispose() { this->~WriteWrap(); delete[] reinterpret_cast(this); } char* WriteWrap::Extra(size_t offset) { return reinterpret_cast(this) + ROUND_UP(sizeof(*this), kAlignSize) + offset; } size_t WriteWrap::ExtraSize() const { return storage_size_ - ROUND_UP(sizeof(*this), kAlignSize); } } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_STREAM_BASE_INL_H_