Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7338340
feat: migrate from experimental decorators to TC39 Stage 3 decorators
RaananW Mar 20, 2026
f2fc3ad
fix: update tslib import to use installed package instead of hardcode…
RaananW Mar 20, 2026
c397543
fix: resolve rebase conflicts and fix TC39 decorator migration issues
RaananW Mar 27, 2026
a999fe7
fix: resolve TC39 decorator compat issues - use declare without overr…
RaananW Mar 30, 2026
3a261a0
merge: resolve conflicts with origin/master
RaananW Apr 20, 2026
6b0f70e
fix: migrate new openpbrMaterial fields to TC39 accessor decorator pa…
RaananW Apr 20, 2026
f65c551
fix: resolve post-merge TC39 decorator compat issues
RaananW May 4, 2026
34d6c12
fix: remove override from declare fields (TS1243)
RaananW May 4, 2026
8c4625e
Merge remote-tracking branch 'upstream/master' into feature/tc39-deco…
RaananW May 4, 2026
a4cf0f2
fix: polyfill Symbol.metadata for TC39 decorator metadata support
RaananW May 4, 2026
e5db097
fix: replace Object.hasOwn with hasOwnProperty.call for Babylon Nativ…
RaananW May 5, 2026
e0c6b04
fix: replace remaining Object.hasOwn usages and remove es2022.object …
RaananW May 5, 2026
37a77f0
Fix TC39 decorator visual regressions
RaananW May 6, 2026
f43fd30
Prevent viewer idle render mutation loop
RaananW May 6, 2026
463fbb9
Fix PBR volume IOR decorator migration
RaananW May 6, 2026
fe60746
Remove stale PBR volume IOR expect error
RaananW May 6, 2026
d45231a
Merge remote-tracking branch 'upstream/master' into feature/tc39-deco…
RaananW May 11, 2026
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
255 changes: 4 additions & 251 deletions packages/dev/buildTools/src/pathTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,256 +225,9 @@ function TransformerFactory<T extends TransformerNode>(context: ts.Transformatio
export const storeTsLib = () => {
const tsLibPath = path.resolve(path.resolve(".", "tslib.es6.js"));
if (!fs.existsSync(tsLibPath)) {
fs.writeFileSync(tsLibPath, TslibContent);
// Read from the installed tslib package instead of using a hardcoded copy,
// so that the helpers stay in sync with the TypeScript version.
const tslibSource = require.resolve("tslib/tslib.es6.mjs");
fs.copyFileSync(tslibSource, tsLibPath);
}
};

// tslib 2.4.0
const TslibContent = `
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */

var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};

export function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}

export var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
}
return __assign.apply(this, arguments);
}

export function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}

export function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}

export function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
}

export function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}

export function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}

export function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}

export var __createBinding = Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});

export function __exportStar(m, o) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);
}

export function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}

export function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}

/** @deprecated */
export function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}

/** @deprecated */
export function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}

export function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}

export function __await(v) {
return this instanceof __await ? (this.v = v, this) : new __await(v);
}

export function __asyncGenerator(thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
}

export function __asyncDelegator(o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
}

export function __asyncValues(o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
}

export function __makeTemplateObject(cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};

var __setModuleDefault = Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
};

export function __importStar(mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
}

export function __importDefault(mod) {
return (mod && mod.__esModule) ? mod : { default: mod };
}

export function __classPrivateFieldGet(receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
}

export function __classPrivateFieldSet(receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
}

export function __classPrivateFieldIn(state, receiver) {
if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object");
return typeof state === "function" ? receiver === state : state.has(receiver);
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ export class BakedVertexAnimationManager implements IBakedVertexAnimationManager
*/
@serializeAsTexture()
@expandToProperty("_markSubMeshesAsAttributesDirty")
public texture: Nullable<BaseTexture>;
public accessor texture: Nullable<BaseTexture>;

private _isEnabled = true;
/**
* Enable or disable the vertex animation manager
*/
@serialize()
@expandToProperty("_markSubMeshesAsAttributesDirty")
public isEnabled = true;
public accessor isEnabled = true;

/**
* The animation parameters for the mesh. See setAnimationParameters()
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/core/src/Cameras/arcRotateCamera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ export class ArcRotateCamera extends TargetCamera {
/**
* Defines the input associated to the camera.
*/
public override inputs: ArcRotateCameraInputsManager;
declare public inputs: ArcRotateCameraInputsManager;

/** @internal */
public override _reset: () => void;
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/core/src/Cameras/followCamera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ export class FollowCamera extends TargetCamera {
* Define the target of the camera.
*/
@serializeAsMeshReference("lockedTargetId")
public override lockedTarget: Nullable<AbstractMesh>;
public override lockedTarget: Nullable<AbstractMesh> = null;

/**
* Defines the input associated with the camera.
*/
public override inputs: FollowCameraInputsManager;
declare public inputs: FollowCameraInputsManager;

/**
* Instantiates the follow camera.
Expand Down
44 changes: 38 additions & 6 deletions packages/dev/core/src/Decorators/nodeDecorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,51 @@ export function editableInPropertyPage(
groupName: string = "PROPERTIES",
options?: IEditablePropertyOption
) {
return (target: any, propertyKey: string) => {
let propStore: IPropertyDescriptionForEdition[] = target._propStore;
if (!propStore) {
return (_value: unknown, context: { name: string | symbol; metadata: DecoratorMetadataObject }) => {
const meta = context.metadata;
let propStore: IPropertyDescriptionForEdition[];
if (Object.prototype.hasOwnProperty.call(meta, __bjsPropStoreKey)) {
propStore = meta[__bjsPropStoreKey] as IPropertyDescriptionForEdition[];
} else {
propStore = [];
target._propStore = propStore;
meta[__bjsPropStoreKey] = propStore;
}
propStore.push({
propertyName: propertyKey,
propertyName: String(context.name),
displayName: displayName,
type: propertyType,
groupName: groupName,
options: options ?? {},
className: target.getClassName(),
className: "",
});
};
}

/** @internal */
// eslint-disable-next-line @typescript-eslint/naming-convention
export const __bjsPropStoreKey = "__bjs_prop_store__";

/**
* Gets the editable properties for a given target using TC39 decorator metadata.
* Walks the metadata prototype chain to include properties from parent classes.
* @param target - the target object (instance or constructor)
* @returns array of property descriptions
*/
export function GetEditableProperties(target: any): IPropertyDescriptionForEdition[] {
const ctor = typeof target === "function" ? target : target?.constructor;
const metadata: DecoratorMetadataObject | undefined = ctor?.[Symbol.metadata];
if (!metadata) {
return [];
}

const result: IPropertyDescriptionForEdition[] = [];
let currentMeta: any = metadata;
while (currentMeta) {
if (Object.prototype.hasOwnProperty.call(currentMeta, __bjsPropStoreKey)) {
const store = currentMeta[__bjsPropStoreKey] as IPropertyDescriptionForEdition[];
result.push(...store);
}
currentMeta = Object.getPrototypeOf(currentMeta);
}
return result;
}
2 changes: 1 addition & 1 deletion packages/dev/core/src/Layers/glowLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class GlowLayer extends EffectLayer {
@serialize("options")
protected _options: IGlowLayerOptions;

protected override readonly _thinEffectLayer: ThinGlowLayer;
declare protected readonly _thinEffectLayer: ThinGlowLayer;
private _horizontalBlurPostprocess1: BlurPostProcess;
private _verticalBlurPostprocess1: BlurPostProcess;
private _horizontalBlurPostprocess2: BlurPostProcess;
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/core/src/Layers/highlightLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ interface IBlurPostProcess extends PostProcess {
* It enforces keeping the most luminous color in the color channel.
*/
class GlowBlurPostProcess extends PostProcess {
protected override _effectWrapper: ThinGlowBlurPostProcess;
declare protected _effectWrapper: ThinGlowBlurPostProcess;

constructor(
name: string,
Expand Down Expand Up @@ -229,7 +229,7 @@ export class HighlightLayer extends EffectLayer {
@serialize("options")
private _options: Required<IHighlightLayerOptions>;

protected override readonly _thinEffectLayer: ThinHighlightLayer;
declare protected readonly _thinEffectLayer: ThinHighlightLayer;
private _downSamplePostprocess: PassPostProcess;
private _horizontalBlurPostprocess: IBlurPostProcess;
private _verticalBlurPostprocess: IBlurPostProcess;
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/core/src/Layers/selectionOutlineLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class SelectionOutlineLayer extends EffectLayer {
@serialize("options")
private _options: Required<ISelectionOutlineLayerOptions>;

protected override readonly _thinEffectLayer: ThinSelectionOutlineLayer;
declare protected readonly _thinEffectLayer: ThinSelectionOutlineLayer;

/**
* Instantiates a new selection outline Layer and references it to the scene..
Expand Down
Loading
Loading