Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 45 additions & 5 deletions NativeScript/runtime/ClassBuilder.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#ifndef ClassBuilder_h
#define ClassBuilder_h

#include <string>
#include <unordered_set>
#include <vector>

#include "Common.h"
#include "Metadata.h"

Expand Down Expand Up @@ -38,6 +42,37 @@ class ClassBuilder {
static std::string GetTypeEncoding(const TypeEncoding* typeEncoding,
int argsCount);

// Defines the global `__registerNativeClass(ctor)` used by NativeClass to
// register eagerly. No-ops on worker isolates, whose class names are
// isolate-suffixed and so cannot answer name-based native lookups.
static void RegisterNativeClassFunction(v8::Local<v8::Context> context);

// Lazily registers an Objective-C subclass for a plain ES
// `class X extends NativeBase {}` constructor function. Returns the
// registered class, or nil when ctorFunc is not part of a native inheritance
// chain; throws when the chain goes through a legacy `.extend()`-created
// class. Idempotent: subsequent calls return the cached class from the ctor's
// ObjCClassWrapper. Pass nativeAllocates when the caller is handing the class
// to Objective-C (or allocating through it), which is what makes the JS
// constructor unreachable and gates the debug diagnostic.
static Class EnsureExtendedClass(v8::Local<v8::Context> context,
v8::Local<v8::Function> ctorFunc,
bool nativeAllocates = false);

// Resolves the Objective-C class that should be instantiated for a construct
// call, honoring `new.target` so that plain ES subclasses of native classes
// get their own registered class.
static Class ResolveConstructedClass(v8::Local<v8::Context> context,
v8::Local<v8::Value> newTarget,
Class fallback);

// Throws unless a super(...) call from a plain ES subclass uses a form that
// names exactly one initializer. Call after ResolveConstructedClass, which
// is what marks new.target as ES-derived.
static void ValidateEsClassSuperArgs(
v8::Local<v8::Context> context,
const v8::FunctionCallbackInfo<v8::Value>& info);

private:
static std::atomic<unsigned long long> classNameCounter_;

Expand All @@ -47,11 +82,16 @@ class ClassBuilder {
static void ExtendedClassConstructorCallback(
const v8::FunctionCallbackInfo<v8::Value>& info);

static void ExposeDynamicMethods(v8::Local<v8::Context> context,
Class extendedClass,
v8::Local<v8::Value> exposedMethods,
v8::Local<v8::Value> exposedProtocols,
v8::Local<v8::Object> implementationObject);
static void SwizzleRetainRelease(v8::Isolate* isolate, Class extendedClass);
static void WarnIfConstructorIsUnreachable(
v8::Local<v8::Context> context,
const std::vector<v8::Local<v8::Function>>& chainCtors, Class extendedClass);
static void ExposeDynamicMethods(
v8::Local<v8::Context> context, Class extendedClass,
v8::Local<v8::Value> exposedMethods,
v8::Local<v8::Value> exposedProtocols,
v8::Local<v8::Object> implementationObject,
std::unordered_set<std::string>* visitedNames = nullptr);
static void ExposeDynamicMembers(v8::Local<v8::Context> context,
Class extendedClass,
v8::Local<v8::Object> implementationObject,
Expand Down
Loading
Loading