im trying to learn gjs and having a few questions which i think are basic about ParamFlags.
I'm creating a subclass and trying to use GObject.ParamFlags.CONSTRUCT_ONLY | GObject.ParamFlags.READABLE for one of the parameters. The use case being what it sounds like, being able to set it only during construction and later being able to read it. I'm declaring it like:
magic_word: GObject.ParamSpec.string(
"magic-word",
"Magic word",
"My magic word",
GObject.ParamFlags.CONSTRUCT_ONLY | GObject.ParamFlags.READABLE,
"magicword default value"
),
But this throws the following error during module loading.
GLib-GObject-CRITICAL **: 14:18:53.750: validate_pspec_to_install: assertion 'pspec->flags & G_PARAM_WRITABLE' failed
It still allows the program to continue execution though.
It seems the only way to get this error to stop is to also give it the WRITABLE or READWRITE flag and perhaps implement the desired behavior through getter/setter. But then the purpose of CONSTRUCT_ONLY seems lost. What am I missing?
G_PARAM_CONSTRUCT_ONLY means a property can only be set during construction, implying that the property must be writable. In other words, CONSTRUCT_ONLY is simply a constraint on WRITABLE.
The merge request adding JS-level support for G_PARAM_CONSTRUCT_ONLY might help clarify how this works in GJS: https://gitlab.gnome.org/GNOME/gjs/-/merge_requests/377. Keep in mind this was only merged in November 2020.
Related
I'm trying to read a JSON array. Every time i try to read the array/value by passing JSON object key like this-
json[key]
It shows a Eslint error-
[eslint] Generic Object Injection Sink (security/detect-object-injection)
I understand its a security warning because the key may not exists. But how do i resolve this warning? Is there any easier way to read the Json object. My plan is to pass the "key" to the function and read the json based on the key.
You are searching for an ES lint error fix:
Here is the syntax for it
json [`${key}`]
Example:
const obj = {
eventName: 'Music event',
landingPic: 'landing.jpg',
eventPic0: 'pic0.jpg',
eventPic1: 'pic1.jpg',
eventPic2: 'pic2.jpg',
eventPic3: 'pic3.jpg',
artist: 'Elie'
};
// array of keys which need to be read
const arrayOfKey = ['landingPic', 'eventPic0', 'eventPic1', 'eventPic2', 'eventPic3'];
// let's read the value by a key in array
arrayOfKey.forEach( key => {
const value = obj[`${key}`];
console.log(value);
});
There is a good answer here. In general this rule is for paranoiac and the article to which everyone appeal is a mislead. So the best answer, I would say is to turn this rule off, if you can for sure.
And another answer in the comments refers to eslint contributor answer that this rule is pretty false positive prone and more for human to audit a codebase(warning level) rather then give an error in a CI. So I would say you can totally ignore this rule or turn it off.
If you cannot turn it off or ignore, you can disable the eslint for line with comment that it's a false positive or use some interpolation as mentioned in other answers.
And finally, in order to destroy any doubts, the answer from creator of the rule:
"I'm the original author of this rule - for a bit of context, it was originally written as an assistive tool for manual code reviews, to be
used with the eslint plugin for VS Code. I would recommend disabling
it for other use cases, as it's just going to be far too noisy."
Unsure why, but typecasting the access parameter silences the error. Guessing this has something to do with sanitation being able to prevent pollution.
const myThing = myObj[String(key)]
const myThing = myObj[key as string]
What its trying to say is that using this notation:
You are able to modify even prototype properties of the object which is considered dangerous
By being able to modify everything, you are also able to modify the constructor (method/function) so it may be injected and then exploited.
The subject is described analytically here, providing a simple example:
https://web.archive.org/web/20150430062816/https://blog.liftsecurity.io/2015/01/15/the-dangers-of-square-bracket-notation
I'm trying to read a JSON array. Every time i try to read the array/value by passing JSON object key like this-
json[key]
It shows a Eslint error-
[eslint] Generic Object Injection Sink (security/detect-object-injection)
I understand its a security warning because the key may not exists. But how do i resolve this warning? Is there any easier way to read the Json object. My plan is to pass the "key" to the function and read the json based on the key.
You are searching for an ES lint error fix:
Here is the syntax for it
json [`${key}`]
Example:
const obj = {
eventName: 'Music event',
landingPic: 'landing.jpg',
eventPic0: 'pic0.jpg',
eventPic1: 'pic1.jpg',
eventPic2: 'pic2.jpg',
eventPic3: 'pic3.jpg',
artist: 'Elie'
};
// array of keys which need to be read
const arrayOfKey = ['landingPic', 'eventPic0', 'eventPic1', 'eventPic2', 'eventPic3'];
// let's read the value by a key in array
arrayOfKey.forEach( key => {
const value = obj[`${key}`];
console.log(value);
});
There is a good answer here. In general this rule is for paranoiac and the article to which everyone appeal is a mislead. So the best answer, I would say is to turn this rule off, if you can for sure.
And another answer in the comments refers to eslint contributor answer that this rule is pretty false positive prone and more for human to audit a codebase(warning level) rather then give an error in a CI. So I would say you can totally ignore this rule or turn it off.
If you cannot turn it off or ignore, you can disable the eslint for line with comment that it's a false positive or use some interpolation as mentioned in other answers.
And finally, in order to destroy any doubts, the answer from creator of the rule:
"I'm the original author of this rule - for a bit of context, it was originally written as an assistive tool for manual code reviews, to be
used with the eslint plugin for VS Code. I would recommend disabling
it for other use cases, as it's just going to be far too noisy."
Unsure why, but typecasting the access parameter silences the error. Guessing this has something to do with sanitation being able to prevent pollution.
const myThing = myObj[String(key)]
const myThing = myObj[key as string]
What its trying to say is that using this notation:
You are able to modify even prototype properties of the object which is considered dangerous
By being able to modify everything, you are also able to modify the constructor (method/function) so it may be injected and then exploited.
The subject is described analytically here, providing a simple example:
https://web.archive.org/web/20150430062816/https://blog.liftsecurity.io/2015/01/15/the-dangers-of-square-bracket-notation
I understand the below line of code is horrible coding, but my question is why does this type of code not produce a console error, and simply halt execution instead?
Example:
Assuming that there is a session storage item called mySessionItem, and its value is JSON with the property myObjectProperty in it, the following code when executed will work when the session storage item is set and has valid JSON.
let myVar = JSON.parse(sessionStorage.getItem("mySessionItem"))["myObjectProperty"] === "myValue" ? false : true;
However if the session storage is not set, or is set to invalid JSON, or valid JSON but is missing the property myProperty, it errors and halts execution.
This is normal behavior and something I would expect from such poor code. However this does not produce a console error, making it extremely difficult to track down.
Is there a reason that this does not result in a console error, is there any way I can force it to generate one programatically, and is there any easy way to track down issues like this?
I work on a large team with members of varying levels of coding ability, and as things like this enter the code-base I'd like to find better ways of tracking them since they can be quite elusive in a large application and wreak havoc everywhere.
For reference our team is using Angular 2 implemented via the Angular CLI using TypeScript. I'm not sure if one of these things plays a role in the bad code generating an error not so I wanted to make sure that I emphasized what tools we were using.
You could do something like create a class in Typescript for the session object then try to access the property since that class will always have that property.
> let myVar: boolean = new Session(JSON.parse(sessionStorage.getItem("mySessionItem"))).myObjectProperty === "myValue" ? false : true;
This uses some of the type-safety features of Typescript and you get to control what happens to the session Object in the constructor if lets say the property is not set or missing.
constructor(options: { myObjectProperty?: string } = {}){
this.myPropertyObject = options.myPropertyObject || '';
}
Why is that Object.freeze(obj) is made to fail silently when obj is mutated?
Wouldn't it be more logical to throw than error when an immutable object is mutated? Then, it would be to the user's discretion if he wants to wrap a try catch around his Object.freeze(obj). Similar to how we need to wrap JSON.parse() with try catch to avoid errors with empty strings or malformed JSON's.
I wish if the community can make a comment.
Edit after few answers and comments:
It is understood that Object.frozen() throws error in strict mode. But why is it necessary for the method to fail silently in non-strict mode?
Object.freeze() does throw, in strict mode.
In strict mode, the following program will throw any time a property is added, mutated or deleted on the frozen object.
Assume we have
'use strict'
const obj = Object.freeze({ test: true })
Error when adding a property:
obj.other = true
// TypeError: Can't add property another, object is not extensible
Mutating an existing property throws:
obj.test = false
// TypeError: Cannot assign to read only property 'test' of object '#<Object>'
Deleting a property throws:
delete obj.test
TypeError: Cannot delete property 'test' of #<Object>
If would like to understand strict mode in more detail (highly recommended) have a look at the official MDN docs for the differences.
The opinions on this topic vary - one would expect mutations of the object to throw because "you are doing something you should not be doing" while others might say that if you Object.freeze() something, you just want to prevent any modifications to it. And that you successfully accomplish. If it caused applications to crash on mutations, programmers would have no choice but to either check all objects they did not create for their frozenness or they would have to wrap all such operations in try/catch block. This is simply too much to ask.
Note about try/catch
You can avoid wrapping property manipulations in try/catch blocks simply by checking the object's temperature 😎:
if (Object.isFrozen(obj) {
// Can't touch this!
}
I think this is why modifying a frozen object fails silently,
If error is thrown, execution of code will stop. Try and catch
statements are available to handle the error. Is it okay to use try
and catch statements for every line in your code to avoid the error?
I think no
1. Unnecessary use of try and catch blocks in code
Let's say an object is frozen at some point in the flow of control. There maybe many lines in code which try to add a new property or modify the value of an existing property in the frozen object. In this scenario, if error is thrown, then you need to add try and catch blocks in all those lines of code.
2. Any number of objects can be freezed
Let's say more than one object is freezed. This will increase the need for more try and catch statements. It may lead to enclosing each line of your code with a try and catch block
For the most part, the library I'm developing is going to be consumed internally by one or more projects. With that in mind, should I add logic that performs type checking on all parameters for functions I write, on some parameters or none? To do selective type checking, I feel, would create an inconsitent feel to the API, to do it for all parameters would bloat the code, and to do it for none could lead to error messages that aren't helpful. Any guidance as to why or why not would be appreciated.
First of all, it is important that you document your API, even if it's only for internal use. It comes in handy if you need your code some years later.
In this documentation you can tell the user what type the parameters should be. An often used tool for documentation is doxygen:
/**
* \brief Converts a string into a DummyObject
* \param str should be a valid string
*/
function str_to_dummy(str) {
}
/**
* \brief Converts an object into a DummyObject
* \param jsobj should be an object which contains at least
* the following attibutes: 'height','length', 'size'
* \example json_to_dummy({'height': 12,'length': 15,'size': 11});
*/
function json_to_dummy(jsobj) {
}
Keep in mind that the user will experience an error message either way, either:
Parameter 'o' must be an object with attribute 'height'
or
ReferenceError: o.height is undefined
While it is nice to get a more verbose error, it often isn't necessary if you document your API correctly.
I guess it all comes down to how well you want to handle errors in your library. Can you live with the fact that someone passes you arguments of invalid type (even though, I'm assuming, documentation states clearly what he/she should pass)? If you're ok with that I would skip type checking to save on library size.
After all it's only client-side javascript if someone wants to tamper with it he will. There's nothing you can do about it.
I think you (almost) always should check or cast function parameters.
I just had smth. like this yesterday:
foo("1");
function foo(myVar)
{
return myVar+2;
}
So you should be careful. I believe it is a good reason.