feat: 50 игр на Lua + импорт Roblox для всех + поддержка Lua в плеере #39
@ -274,6 +274,42 @@ function isProbablySignalName(prop) {
|
|||||||
|| /(Changed|Added|Removed|Began|Ended|Clicked|Activated|Touched|Died|Loaded|Hover|Connect|Event|Signal|Reached)$/.test(prop);
|
|| /(Changed|Added|Removed|Began|Ended|Clicked|Activated|Touched|Died|Loaded|Hover|Connect|Event|Signal|Reached)$/.test(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Callable stub: функция которая ничего не делает + поля Connect/Wait/Fire,
|
||||||
|
// чтобы выглядеть и как метод (`obj:Method()`), и как сигнал (`sig:Connect()`),
|
||||||
|
// и как объект (`obj.Property`).
|
||||||
|
function makeCallableStub(name) {
|
||||||
|
// Используем function чтобы Proxy мог иметь apply trap
|
||||||
|
const fnTarget = function () { return fnTarget; };
|
||||||
|
fnTarget.__stubName = name || 'stub';
|
||||||
|
fnTarget.Connect = function () { return { Disconnect: () => {}, disconnect: () => {}, Connected: false }; };
|
||||||
|
fnTarget.connect = fnTarget.Connect;
|
||||||
|
fnTarget.Wait = function () { return undefined; };
|
||||||
|
fnTarget.wait = fnTarget.Wait;
|
||||||
|
fnTarget.Fire = function () { return undefined; };
|
||||||
|
fnTarget.fire = fnTarget.Fire;
|
||||||
|
fnTarget.Disconnect = function () {};
|
||||||
|
fnTarget.disconnect = fnTarget.Disconnect;
|
||||||
|
// Proxy чтобы любое доступ к unknown полю/индексу возвращал тот же stub
|
||||||
|
return new Proxy(fnTarget, {
|
||||||
|
get(t, prop) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(t, prop) || prop in t) {
|
||||||
|
return t[prop];
|
||||||
|
}
|
||||||
|
if (typeof prop !== 'string') return undefined;
|
||||||
|
if (prop === 'then' || prop === 'catch' || prop === 'finally' ||
|
||||||
|
prop === 'toJSON' || prop === 'constructor' || prop === 'prototype' ||
|
||||||
|
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const child = makeCallableStub(prop);
|
||||||
|
t[prop] = child;
|
||||||
|
return child;
|
||||||
|
},
|
||||||
|
set(t, prop, value) { t[prop] = value; return true; },
|
||||||
|
apply() { return fnTarget; }, // obj() возвращает себя
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function newInstance(className, name) {
|
function newInstance(className, name) {
|
||||||
const m = makeInstanceMethods();
|
const m = makeInstanceMethods();
|
||||||
const target = {
|
const target = {
|
||||||
@ -318,15 +354,10 @@ function newInstance(className, name) {
|
|||||||
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
prop.startsWith('__') || prop.startsWith('Symbol')) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
// Эвристика: имена сигналов → stub-сигнал. Иначе — stub-Folder.
|
// Callable-stub: можно вызвать как функцию, как сигнал (:Connect),
|
||||||
// Stub-Folder сам по себе callable (на случай если скрипт его вызовет
|
// как объект (.Property), как child Instance (.WaitForChild). Не падает
|
||||||
// как функцию: `foo()` вместо `foo:Connect()` — оба не падают).
|
// на любом обращении со стороны импортированных скриптов.
|
||||||
let stub;
|
const stub = makeCallableStub(prop);
|
||||||
if (isProbablySignalName(prop)) {
|
|
||||||
stub = makeStubSignal();
|
|
||||||
} else {
|
|
||||||
stub = newInstance('Folder', prop);
|
|
||||||
}
|
|
||||||
t[prop] = stub;
|
t[prop] = stub;
|
||||||
return stub;
|
return stub;
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user