void PushWeakObject(duk_context* ctx, Object* object) { if (!object) { duk_push_null(ctx); return; } duk_push_heap_stash(ctx); // Check if the wrapper for the object already exists in stash // This is required so that comparisons of object references (e.g. against the me property) work properly if (duk_has_prop_index(ctx, -1, (size_t)object)) { duk_get_prop_index(ctx, -1, (size_t)object); WeakPtr<Object>* oldPtr = GetWeakPtr(ctx, -1); if (oldPtr && oldPtr->Get() == object) { duk_remove(ctx, -2); // Remove stash return; } else duk_pop(ctx); // Valid existing wrapper not found } duk_push_object(ctx); WeakPtr<Object>* ptr = new WeakPtr<Object>(object); duk_push_pointer(ctx, ptr); duk_put_prop_string(ctx, -2, "\xff""weak"); duk_push_c_function(ctx, WeakPtr_Finalizer, 1); duk_set_finalizer(ctx, -2); // Set prototype. If not found, use base class prototype (e.g. IComponent) duk_get_global_string(ctx, object->GetTypeName().CString()); if (!duk_is_object(ctx, -1)) { duk_pop(ctx); duk_get_global_string(ctx, object->GetTypeInfo()->GetBaseTypeInfo()->GetTypeName().CString()); } duk_get_prop_string(ctx, -1, "prototype"); duk_set_prototype(ctx, -3); duk_pop(ctx); // Proxied property access handling for scene, entity & component if (object->GetType() == Scene::GetTypeStatic()) SetupProxy(ctx, SceneProxyFunctions); if (object->GetType() == Entity::GetTypeStatic()) SetupProxy(ctx, EntityProxyFunctions); else if (dynamic_cast<IComponent*>(object)) SetupProxy(ctx, ComponentProxyFunctions); // Store to stash duk_dup(ctx, -1); duk_put_prop_index(ctx, -3, (size_t)object); duk_remove(ctx, -2); // Remove stash }