Use Object.seal and Object.freeze to ensure integrity of builtins

RESOLVED INCOMPLETE

Status

defect
RESOLVED INCOMPLETE
5 years ago
3 years ago

People

(Reporter: till, Unassigned)

Tracking

Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

Reporter

Description

5 years ago
After installing our additions to Object.prototype et al, we should seal as many objects and prototypes as we can, and freeze some of those that we can't seal, to improve integrity.

In debug builds, we can even seal/freeze lots of runtime-created objects to ensure that we don't accidentally add properties where we assume that an object's shape is fixed.
I don't think we don't care about Object.seal and Object.freeze for M4.
Blocks: shumway-1.0
No longer blocks: shumway-m4

Comment 2

4 years ago
(In reply to Till Schneidereit [:till] from comment #0)
> In debug builds, we can even seal/freeze lots of runtime-created objects to
> ensure that we don't accidentally add properties where we assume that an
> object's shape is fixed.

Isn't TypeScript taking care of this part?
Reporter

Comment 3

4 years ago
(In reply to David Bruant from comment #2)
> (In reply to Till Schneidereit [:till] from comment #0)
> > In debug builds, we can even seal/freeze lots of runtime-created objects to
> > ensure that we don't accidentally add properties where we assume that an
> > object's shape is fixed.
> 
> Isn't TypeScript taking care of this part?

How would it? Property declarations in TypeScript are just that: declarations. If you want to be sure you're always initializing all properties in the same order, you have to do it in the constructor just as always. Well, or give them default values at the declaration site, but again, that's something you have to do, not something that the system takes care of for you - or even warns you about if you get it wrong.

Comment 4

4 years ago
I don't understand your answer. What I was trying to say is that TypeScript warns about properties "accidentally" added:
See: http://www.typescriptlang.org/Playground#src=var o %3D {%0A%09a%3A1%2C%0A%09b%3A2%0A}%3B%0A%0Ao.c %3D 3%3B
(select the URL to copy/paste it, I'm afraid Bugzilla won't like the spaces)

So if you only ship code that is TypeScript-warning-free, the object shapes should be pretty much guaranteed not to change at runtime.
This is assuming you don't use any form of eval (which I imagine you don't) and assuming you don't pass objects to hostile JS code that would be running alongside Shumway's (which you don't do either?)


> If you want to be sure you're always initializing all properties in the same order, you have to do it in the constructor just as always.

Sure, but I don't understand how sealing/freezing would help with this issue either.
Reporter

Comment 5

4 years ago
(In reply to David Bruant from comment #4)
> I don't understand your answer. What I was trying to say is that TypeScript
> warns about properties "accidentally" added:
<snip>
> > If you want to be sure you're always initializing all properties in the same order, you have to do it in the constructor just as always.
> 
> Sure, but I don't understand how sealing/freezing would help with this issue
> either.

I guess my initial description wasn't entirely clear. What I meant by "accidental" wasn't that properties would be added that are allowed where we add them according to our type definitions. What I meant was that in some cases we don't initialize all properties in the constructor, in which case they simply don't exist. TypeScript's property declarations don't result in any code getting generated on their own.

Here's an example of what I mean:

===

class Foo {
  a: string;
  b: boolean;
  c: boolean;
  constructor(a) {
    this.a = a;
  }
}

var f = new Foo('bar');
if (someCondition)
  f.b = true;
else
  f.c = true;

===

Now this code will, depending on the value of `someCondition`, create objects with different shapes. That can be prevented by initializing `b` and `c` in the constructor. However, you can easily forget to do that when you add new properties later. Hence:


  constructor(a) {
    this.a = a;
    this.b = false;
    this.c = false;
    Object.seal(this);
  }

Now, if you forgot to initialize a newly-added property, you'll get an exception the first time you try to actually use it.

Comment 6

4 years ago
> However, you can easily forget to do that when you add new properties later. Hence:
> 
>   constructor(a) {
>     this.a = a;
>     this.b = false;
>     this.c = false;
>     Object.seal(this);
>   }
> 
> Now, if you forgot to initialize a newly-added property, you'll get an
> exception the first time you try to actually use it.
I see. Indeed, there is no way in TypeScript to guarantee an object exits the constructor having all of its properties initialized.

Thanks for the explanations :-)
Product: Firefox → Firefox Graveyard
Status: NEW → RESOLVED
Last Resolved: 3 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.