Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

console.log fails with const object = { __proto__: null } #13

Closed
jsprog opened this issue Nov 11, 2020 · 6 comments
Closed

console.log fails with const object = { __proto__: null } #13

jsprog opened this issue Nov 11, 2020 · 6 comments

Comments

@jsprog
Copy link

jsprog commented Nov 11, 2020

@c-smile Thanks for this link rollup/rollup#3140. I understand that they're sticking to the deprecated __proto__ for performance reasons to avoid changing object's prototype after it's creation (it's supported by browsers and some other runtimes including quickjs)

And according to this rollup/rollup#3096, __proto__: null is used to set the prototype of namespace objects to null.

quickjs has __proto__ according to these links:

What I discovered:

  • The Error only fires when using console.log(object_with__proto__null)
  • The Error won't fire when using __proto__: undefined (not tested with browsers)
  • You can access the object and assign it, but the moment you console.log the second reference, you'll receive the same error.
  • You can console.log object's properties and Object.keys(object).
  • The error has nothing to do with Object.freeze

Test Code:

const obj = {
    __proto__: null,
    a: 10,
    b: 20
};

obj; // Ok

obj.a = 11; // Ok
console.log('obj.a:', obj.a); // Ok: property changed to 11

Object.defineProperty(obj, 'a', { value: 12 });
console.log('obj.a:', obj.a); // Ok: property changed to 12

console.log('keys:', Object.keys(obj)); // Ok: not a problem at all

console.log('obj:', obj); // error
console.log(obj); // the same error
// error message:
// terminate called after throwing an instance of 'qjs::exception'
// Aborted (core dumped)

const obj_2 = obj; // Ok
console.log(obj_2); // The same error because it's refering to the same object

const obj_3 = { ...obj }; // Ok
console.log(obj_3); // Ok
@jsprog
Copy link
Author

jsprog commented Nov 12, 2020

Unlike Chrome and Firefox, The current implementation of quickjs' console.log depends on the toString method. I already executed some tests under:

  • The version provided by sciter.js (qjs)
  • A Linux build (make) of the last version of quickjs (2020-11-08) https://bellard.org/quickjs/
  • The online interactive version

Test under qjs (either the official version or the one that comes with sciter.js:

let obj = { prop1: 10, prop2: 20 }
console.log(Object.keys(obj)) // prop1,prop2
console.log(obj.toString()) // [object Object]
console.log(obj) // [object object]

obj = { __proto__: null, prop1: 30, prop2: 40 }
console.log(Object.keys(obj)) // prop1,prop2
console.log(obj.toString()) // TypeError: not a function
                            // at <eval> (./log_obj_with__proto__null.js:8)
console.log(obj) // TypeError: toPrimitive
                 //     at log (native)
                 //     at <eval> (./log_obj_with__proto__null.js:10)

The same test at https://bellard.org/jslinux/vm.html?url=alpine-x86.cfg:

Screenshot from 2020-11-12 12-36-33

Note: I'm not in a position to decide behalf others if console.log should behave differently from the current implementation. I can still write something like console.log({...obj}) or even get rid of __proto__:null whenever needed. Let's hear what others have to say about this.

@4silvertooth
Copy link
Contributor

4silvertooth commented Nov 12, 2020

Why is it so important to console.log an object with __proto__ :null, I mean I feel you have invested a lot time on it. What's the importance?

@c-smile
Copy link
Owner

c-smile commented Nov 12, 2020

For now console.log is just a placeholder. It is there for initial development.
In different environments console.log and console in general mean different things.
For real app console.log is just a file.write() or something like that.
For app running with inspector console.log will be redefined as inpector.pipe.write and so on.

In any case it can be redefined on script side:

console,log = function(args...) {  }

with proper checks for thing.toString existence.

@jsprog
Copy link
Author

jsprog commented Nov 12, 2020

@4silvertooth

Why is it so important to console.log an object with proto :null,

I don't write __proto__ in my code. I console.log for inspection regardless whether the target contained a prototype or not. It was just a coincidence that rollup injected it. (note: console.log(JSON.stringify(object)) is tested to work)

I mean I feel you have invested a lot time on it. What's the importance?

  • I'm the one who made the noise, I don't fire and forget, but I do something from my side, to later share back the results.
  • I mind about the success of sciter.js to run some popular reactive frameworks.

@c-smile Feel free to close this anytime.

@c-smile
Copy link
Owner

c-smile commented Nov 12, 2020

Thanks a lot for digging it.

I am using toString() in other places so this finding will help there too.

@c-smile
Copy link
Owner

c-smile commented Nov 13, 2020

Fixed in 4.4.5.5

@c-smile c-smile closed this as completed Nov 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants