|
| 1 | +#include "ffi.h" |
| 2 | + |
| 3 | +#include <workerd/jsg/util.h> |
| 4 | +#include <workerd/jsg/wrappable.h> |
| 5 | +#include <workerd/rust/jsg/lib.rs.h> |
| 6 | + |
| 7 | +#include <kj/common.h> |
| 8 | + |
| 9 | +using namespace kj_rs; |
| 10 | + |
| 11 | +namespace workerd::rust::jsg { |
| 12 | + |
| 13 | +v8::Local<v8::FunctionTemplate> get_template( |
| 14 | + v8::Isolate* isolate, const ResourceDescriptor& descriptor) { |
| 15 | + // Construct lazily. |
| 16 | + // v8::EscapableHandleScope scope(isolate); |
| 17 | + |
| 18 | + v8::Local<v8::FunctionTemplate> constructor; |
| 19 | + KJ_IF_SOME(c, descriptor.constructor) { |
| 20 | + KJ_UNIMPLEMENTED("constructors are not implemented yet"); |
| 21 | + // constructor = |
| 22 | + // v8::FunctionTemplate::New(isolate, &ConstructorCallback<TypeWrapper, T>::callback); |
| 23 | + } else { |
| 24 | + constructor = v8::FunctionTemplate::New(isolate, &workerd::jsg::throwIllegalConstructor); |
| 25 | + } |
| 26 | + |
| 27 | + auto prototype = constructor->PrototypeTemplate(); |
| 28 | + |
| 29 | + // Signatures protect our methods from being invoked with the wrong `this`. |
| 30 | + // auto signature = v8::Signature::New(isolate, constructor); |
| 31 | + |
| 32 | + auto instance = constructor->InstanceTemplate(); |
| 33 | + |
| 34 | + instance->SetInternalFieldCount(workerd::jsg::Wrappable::INTERNAL_FIELD_COUNT); |
| 35 | + |
| 36 | + auto classname = ::workerd::jsg::v8StrIntern(isolate, kj::str(descriptor.name)); |
| 37 | + |
| 38 | + if (workerd::jsg::getShouldSetToStringTag(isolate)) { |
| 39 | + prototype->Set(v8::Symbol::GetToStringTag(isolate), classname, v8::PropertyAttribute::DontEnum); |
| 40 | + } |
| 41 | + |
| 42 | + // Previously, miniflare would use the lack of a Symbol.toStringTag on a class to |
| 43 | + // detect a type that came from the runtime. That's obviously a bit problematic because |
| 44 | + // Symbol.toStringTag is required for full compliance on standard web platform APIs. |
| 45 | + // To help use cases where it is necessary to detect if a class is a runtime class, we |
| 46 | + // will add a special symbol to the prototype of the class to indicate. Note that |
| 47 | + // because this uses the global symbol registry user code could still mark their own |
| 48 | + // classes with this symbol but that's unlikely to be a problem in any practical case. |
| 49 | + auto internalMarker = |
| 50 | + v8::Symbol::For(isolate, ::workerd::jsg::v8StrIntern(isolate, "cloudflare:internal-class")); |
| 51 | + prototype->Set(internalMarker, internalMarker, |
| 52 | + static_cast<v8::PropertyAttribute>(v8::PropertyAttribute::DontEnum | |
| 53 | + v8::PropertyAttribute::DontDelete | v8::PropertyAttribute::ReadOnly)); |
| 54 | + |
| 55 | + constructor->SetClassName(classname); |
| 56 | + |
| 57 | + // auto& typeWrapper = static_cast<TypeWrapper&>(*this); |
| 58 | + |
| 59 | + // ResourceTypeBuilder<TypeWrapper, T, isContext> builder( |
| 60 | + // typeWrapper, isolate, constructor, instance, prototype, signature); |
| 61 | + |
| 62 | + // if constexpr (isDetected<GetConfiguration, T>()) { |
| 63 | + // T::template registerMembers<decltype(builder), T>(builder, configuration); |
| 64 | + // } else { |
| 65 | + // T::template registerMembers<decltype(builder), T>(builder); |
| 66 | + // } |
| 67 | + |
| 68 | + for (const auto& method: descriptor.static_methods) { |
| 69 | + auto functionTemplate = v8::FunctionTemplate::New(isolate, |
| 70 | + reinterpret_cast<v8::FunctionCallback>(reinterpret_cast<void*>(method.callback)), |
| 71 | + v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow); |
| 72 | + functionTemplate->RemovePrototype(); |
| 73 | + constructor->Set(::workerd::jsg::v8StrIntern(isolate, kj::str(method.name)), functionTemplate); |
| 74 | + } |
| 75 | + |
| 76 | + for (const auto& method: descriptor.methods) { |
| 77 | + auto functionTemplate = v8::FunctionTemplate::New(isolate, |
| 78 | + reinterpret_cast<v8::FunctionCallback>(reinterpret_cast<void*>(method.callback)), |
| 79 | + v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 0, v8::ConstructorBehavior::kThrow); |
| 80 | + prototype->Set(::workerd::jsg::v8StrIntern(isolate, kj::str(method.name)), functionTemplate); |
| 81 | + } |
| 82 | + |
| 83 | + // auto result = scope.Escape(constructor); |
| 84 | + // slot.Reset(isolate, result); |
| 85 | + return constructor; |
| 86 | +} |
| 87 | + |
| 88 | +LocalValue instantiate_resource(v8::Isolate* isolate, const ResourceDescriptor& descriptor) { |
| 89 | + auto tmpl = get_template(isolate, descriptor); |
| 90 | + v8::Local<v8::Object> object = |
| 91 | + workerd::jsg::check(tmpl->InstanceTemplate()->NewInstance(isolate->GetCurrentContext())); |
| 92 | + return to_repr(object); |
| 93 | +} |
| 94 | + |
| 95 | +} // namespace workerd::rust::jsg |
0 commit comments