Is the treatment of __proto__ different in the fetch API compared to manual assignment?

When using fetch to retrieve a payload containing a __proto__, it seems that the Object prototype is not affected in the same way as when directly assigning to an object.

This behavior is beneficial as it ensures that the Object prototype remains unaffected by any API calls. However, I am curious about the mechanics behind this and why it happens?

For instance, considering a payload.json file:

{
  "__proto__": { "toString": "foobar" }
}

If we fetch this data:

 fetch("payload.json")
      .then(function(response) {
        return response.json();
      })
      .then(function(json) {
        console.log("--JSON from a fetch payload--");
        console.log("payload.toString():", json.toString()); // [object Object]
        console.log("json.__proto__:", json.__proto__); // {toString: "foobar"}
        console.log("{}.toString()", {}.toString()); //[object Object]

        console.log("--New object with __proto__ set--");
        const x = { __proto__: { toString: () => "hacked" } };
        console.log("x.toString(): ", x.toString());
        console.log("{}.toString(): ", {}.toString());
        console.log(
          "JSON.parse('{}').toString(): ",
          JSON.parse("{}").toString()
        );

        console.log("--Set proto with assignment--");
        const y = {};
        y.__proto__.toString = () => "polluted";
        console.log("y.toString(): ", y.toString());
        console.log("x.toString(): ", x.toString());
        console.log("{}.toString(): ", {}.toString());
        console.log(
          "JSON.parse('{}').toString(): ",
          JSON.parse("{}").toString()
        );
      });

The output will be:

--JSON from a fetch payload-- 
payload.toString(): [object Object] 
json.__proto__: 
Object {toString: "foobar"}
{}.toString() [object Object] 
--New object with __proto__ set-- 
x.toString():  *** hacked *** 
{}.toString():  [object Object] 
JSON.parse('{}').toString():  [object Object] 
--Set proto with assignment-- 
y.toString():  *** polluted *** 
x.toString():  *** hacked *** 
{}.toString():  *** polluted *** 
JSON.parse('{}').toString():  *** polluted *** 

I understand how the last example pollutes the object prototype, but I'm intrigued as to why json.__proto__ behaves differently when obtained through a fetch call.

You can view the above example on codesandbox.io

Answer №1

It's important to note that the behavior of fetch API is not related to this issue.

The property __proto__ is a special getter/setter on the Object.prototype, converting operations like [[Get]] and [[Set]] to [[GetPrototypeOf]] and [[SetPrototypeOf]].

When fetching and parsing data as JSON, it operates similarly to JSON.parse: parsing the JSON and creating an empty JavaScript object with the properties added.

However, instead of simply setting the properties using [[Set]], they are defined using [[Define]], which means they won't trigger the setter, resulting in a standard property named __proto__ pointing to a different object than its [[Prototype]]:

Consider the example below:

// Using [[Set]], as initially thought
const obj1 = {}
obj1.__proto__ = {}
console.log(obj1.hasOwnProperty('__proto__')) // false, because it's inherited
console.log(obj1.__proto__ === Object.getPrototypeOf(obj1)) // true

// Using [[Define]], similar to JSON.parse
const obj2 = {}
Object.defineProperty(obj2, '__proto__', {
  value: {},
  enumerable: true,
  configurable: true,
  writable: true
})
console.log(obj2.hasOwnProperty('__proto__')) // true, it is own property
console.log(obj.__proto__ === Object.getPrototypeOf(obj)) // false

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to attach an event listener to an input element using Angular

I am looking to add a listener to an input element that will be triggered every time the user changes the input values. The goal is to display the current values chosen by the user. Example HTML template: <div id="idDoseLabel1" class="da ...

What is the method to display HTML code using JavaScript within a span element in a JSP page?

While working on a jsp file, I came across a span tag with the following code: <span id="divBasicSearchResults" style="height:100%;"></span> Below is the Javascript function that generates HTML content for this span: function renderBasicSear ...

Is there a way to postpone the execution of a scheduled interval function?

Below is the setup of my function: setInterval(function () { get_fb(); }, 10000); If a user interacts with an element, such as hovering over it or clicking on it, I want to reset the timer back to 10 seconds. How can I instruct the program to achieve th ...

Function wrapper intended for axios

How can I create a wrapper function for axios? I am looking to create a function that can return axios, allowing for easy substitution with another fetch API in the future. This is what I have attempted so far: import axios from 'axios' expor ...

When trying to decode a JSON string into a simple Rails object, an unexpected

I am facing an issue while trying to encode and decode plain strings in JSON format, resulting in an error. Previously, in Rails 2.3 with Ruby 1.8.6, this process worked smoothly. >> puts ActiveSupport::JSON.decode("abc".to_json) abc => nil How ...

Steer clear of chaining multiple subscriptions in RXJS to improve code

I have some code that I am trying to optimize: someService.subscribeToChanges().subscribe(value => { const newValue = someArray.find(val => val.id === value.id) if (newValue) { if (value.status === 'someStatus') { ...

"Can you tell me the method for obtaining an array within an Angular

Within the realm of PHP, there exist certain elements within an array: $this->data['messages']['ms'][] = 'Line1'; $this->data['messages']['ms'][] = 'Line2'; along with a method that return ...

Exploring the World of JSON Iteration

At my job, I primarily use a language called AL, but we frequently work with JSON Objects, Arrays, and more. Currently, I am accessing data from this API: , and saving the result in a text variable. My goal is to create a separate table containing the ID ...

Initiate an AJAX call with various data formats included

I am currently developing an application that allows users to input values through an interface and send AJAX requests (similar to a REST API). My question pertains to sending data of multiple types in a single request. For example, here is a scenario: F ...

I am experiencing an issue where the result is not appearing on the input tag within my

<script> <form action="do-add-cek.php" id="myForm" method="post" enctype="multipart/form-data"> <div class="form-group"> <label> ...

Is VueJS2 using the computed property/method to modify Vue data?

My form in Vue is almost complete, but I'm facing an issue with an array that seems to be affecting my Vue.data object directly. Here's the situation: In my code, I have a method called getParams() which returns an object containing all the data ...

Include a new feature within an onClick event

I'm looking to implement a single page application using React.js and I want to incorporate a list within a material-ui drawer. The goal is to dynamically add elements to an array every time a button is clicked, but I'm stuck on how to write this ...

Ways to arrange the JSON array by keys in reverse order utilizing Angular

let data = { '2021-07-20-21:10': { sends: 1, recvs: 1, notSents: 0, rejects: 0, xptSkips: 0, timeouts: 0, appErrors: 0, responseTimeAvg: 172, responseTimeMax: 172, ...

Utilizing Jquery to add a delay and animate the sliding up effect on a recently created element

I am looking to apply a slide-up effect to a newly created element after a specified delay. $("div[data-error='true']").delay(5000).slideUp(500, function () { $("#error-alert").remove(); }); $("div[data-success='true']").delay(5000 ...

React Table in Modal Using Custom Hook State

I'm facing some difficulties with the React useState hook. Currently, I have a modal that pops up after submitting a form. Before loading the modal, the application calls an API to fetch data, which is then displayed in a table within the modal. The ...

Is it considered good or bad practice to use plain JavaScript objects in an AngularJS application?

Imagine needing a custom object that doesn't rely on AngularJS (such as a specific collection with unique functionalities). You could create it independently of AngularJS and simply use it in services/controllers. Alternatively, you could design it a ...

An error of unknown token U was encountered in the JSON data starting at position 0

I am facing an issue with my MEAN Stack development. Currently, I have an Angular Form set up with proper values to create a company in the database using Node Express on the backend. However, I keep encountering an error stating that the JSON in Node is ...

Utilize Fb.api to automatically post on user's wall upon logging in

I want to utilize fb.api to make a single post on the logged-in user's wall. Here is the code snippet: var params = {}; params['message'] = 'gegeegeggegall! Check out www.facebook.com/trashcandyrock for more info.'; params['n ...

Extracting information from an ENORMOUS Array

Let's start with my code snippet, featuring an array: var UserProfiles = [{ userProfileID: 1, firstName: 'Austin', lastName: 'Hunter', email: 'test', token: '', platform: 'android ...

Receiving no feedback from a public API while coding in React.js

I am currently delving into React.js and have been experimenting with a basic form. The issue I am facing is related to sending form data using ajax and not receiving a response. Upon running the code, the console displays an error message stating readysta ...