WebGL rendering incorrect on OffscreenCanvas

I am currently rendering using WebGL, but wanted to move to a worker to unblock the main thread.
Unfortunately, the rendered image changes when using an OffscreenCanvas, and i can’t find any reason why.

An an example, i used the MDN WebGL tutorial and tried to render it to an OffscreenCanvas.

Just by changing canvas.getContext("webgl") to canvas.transferControlToOffscreen().getContext("webgl"), the output changes (Same problem when using the OffscreenCanvas constructor, but i’m using this for simplicity in the example).
The image rendered to the OffscreenCanvas seems to be missing the rectangle drawn using drawArrays, but the background color changes, so WebGL did something.

I couldn’t find anything in the docs to indicate a behaviour change when rendering WebGL to an OffscreenCanvas, so i have no clue why this happens.

Tested on latest Chrome (141.0.7390.66) and Firefox (143.0.4).

https://jsfiddle.net/snv1xabt/1/

Best pattern for create vs edit form in React + Ionic Framework

I am creating an app and am using an Ionic modal to be able to open a view to input information, I am not using react form I am simply using input fields which I validate and onSubmit. I pull the data from a useState form and pass it on to the parent that calls the modal which then converts it into the datatype I need to display the information. I want to be able to use the view to also edit existing information. The wiring is a bit tricky and I am fairly new to react and Ionic. I don’t know much about patterns but I know there’s standards that should be followed with this type of behavior. I know the easiest route is to just create a new view for editing but the purpose of react is to reuse components. ChatGPT is helpful but also confusing me and making me get lost in details and going on tangents. Chat first proposed splitting openModal into openCreate and OpenEdit, and passing a mode and initialValue variable to the modal and tweak behavior accordingly. Then proposed using a small wrapper that calls a generic OpenModal with the initial values and input any other values necessary, I feel like a wrapper complicates things so I am attempting to do the first one. openEdit and createEdit gets a little confusing since the logic in the page is confusing. I am just a little lost if I am headed the right direction. Anyone have any advice?

import {
  IonButtons,
  IonButton,
  IonHeader,
  IonContent,
  IonToolbar,
  IonTitle,
  IonPage,
  IonItem,
  IonInput,
  useIonModal,
} from '@ionic/react';
import { OverlayEventDetail } from '@ionic/core/components';

const ModalExample = ({ dismiss }: { dismiss: (data?: string | null | undefined | number, role?: string) => void }) => {
  const inputRef = useRef<HTMLIonInputElement>(null);
  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonButton color="medium" onClick={() => dismiss(null, 'cancel')}>
              Cancel
            </IonButton>
          </IonButtons>
          <IonTitle>Welcome</IonTitle>
          <IonButtons slot="end">
            <IonButton onClick={() => dismiss(inputRef.current?.value, 'confirm')} strong={true}>
              Confirm
            </IonButton>
          </IonButtons>
        </IonToolbar>
      </IonHeader>
      <IonContent className="ion-padding">
        <IonItem>
          <IonInput ref={inputRef} labelPlacement="stacked" label="Enter your name" placeholder="Your name" />
        </IonItem>
      </IonContent>
    </IonPage>
  );
};

function Example() {
  const [present, dismiss] = useIonModal(ModalExample, {
    dismiss: (data: string, role: string) => dismiss(data, role),
  });
  const [message, setMessage] = useState('This modal example uses the modalController to present and dismiss modals.');

  function openModal() {
    present({
      onWillDismiss: (event: CustomEvent<OverlayEventDetail>) => {
        if (event.detail.role === 'confirm') {
          setMessage(`Hello, ${event.detail.data}!`);
        }
      },
    });
  }

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Controller Modal</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent className="ion-padding">
        <IonButton expand="block" onClick={() => openModal()}>
          Open
        </IonButton>
        <p>{message}</p>
      </IonContent>
    </IonPage>
  );
}

export default Example;```

This is a snippet of what chat proposed for the first solution

    ``` const defaultForm: NewProjectForm = { name: "", totalHouses: 1, description: "" };
    
    const [presentCreate, closeCreate] = useIonModal(ProjectFormModal, {
      onDismiss: (d?: NewProjectForm | null, r?: string) => closeCreate(d, r),
      mode: "create",
      initialForm: defaultForm,
    });
    
    const currentFormRef = useRef<NewProjectForm>(defaultForm);
    
    const [presentEdit, closeEdit] = useIonModal(ProjectFormModal, {
      onDismiss: (d?: NewProjectForm | null, r?: string) => closeEdit(d, r),
      mode: "edit",
      // pass a ref so each open uses the latest value
      initialForm: currentFormRef.current,
      baselineForm: currentFormRef.current,
    });
    
    function openCreate() {
      presentCreate({ onWillDismiss: handleCreateDismiss });
    }
    
    function openEdit(project: ProjectCardProps) {
      currentFormRef.current = projectToForm(project);   // update ref first
      presentEdit({ onWillDismiss: (e) => handleEditDismiss(project.id, e) });
    }
    ```

Three viewports each with a different custom webfont in each. But both viewports display same font

I need to display multiple viewports on a single web page. I have 3 html viewports, each with a different custom webfont. [https://dev.clubtype.co.uk/viewports-my.html] Viewport 1 has the Normal font, viewport 2 has the Italic – so both belong the the same ‘font-family’. Whichever font is specified in viewport 2, it overwrites viewport 1 font. I run into the same issue whether employing, html+css, paragrah formatting or iframe.

Is there a way to prevent this overwriting?

 <!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Custom Font Viewports</title>

  <style>
    /* Define custom fonts using @font-face */
    @font-face {
      font-family: 'Admark Std';
      src:  url('webfonts/AdmarkStd-Regular.woff2') format('woff2'),
        url('webfonts/AdmarkStd-Regular.woff') format('woff');
    }

    @font-face {
      font-family: 'Admark Std';
      src: url('webfonts/AdmarkStd-Italic.woff2') format('woff2'),
        url('webfonts/AdmarkStd-Italic.woff') format('woff');
    }

    @font-face {
      font-family: 'CustomFont3';
      src: url('fonts/CustomFont3.otf') format('opentype');
    }

    /* General styles for input viewports */
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 20px;
      background-color: #f4f4f4;
    }

    .viewport {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 20px;
      border: 2px solid #ccc;
      border-radius: 8px;
      background-color: #fff;
      width: 600px;
    }

    .viewport input {
      width: 100%;
      padding: 10px;
      margin-top: 10px;
      font-size: 36px;
      border: 1px solid #ddd;
      border-radius: 4px;
    }

    /* Apply custom fonts to specific viewports */
    .viewport.font1 input {
      font-family: 'Admark Std', serif;
    }

    .viewport.font2 input {
      font-family: 'Admark Std', serif;
    }

    .viewport.font3 input {
      font-family: 'CustomFont3', sans-serif;
    }
  </style>
</head>
<body>
  <div class="viewport font1">
    <label for="input1">Custom Font 1:</label>
    <input type="text" id="input1" placeholder="Type here...">
  </div>

  <div class="viewport font2">
    <label for="input2">Custom Font 2:</label>
    <input type="text" id="input2" placeholder="Type here...">
  </div>

  <div class="viewport font3">
    <label for="input3">Custom Font 3:</label>
    <input type="text" id="input3" placeholder="Type here...">
  </div>
</body>
</html>

calculator result -my result contains extra number(my second number)

i am writing a calculator with javascript,when i want to display result of calculation the result contains extra number (my second number is showing beside the result).the result contains result+secnum

let memory = document.getElementById('memory');
let num = document.getElementById('inp-num');
let firstnum = 0;
let secnum = 0;
let operand = '';
let result = 0;

let numbutt = document.querySelector('#numbers');
numbutt.addEventListener('click', (event) => {
  let target = event.target;
  switch (target.value) {
    case '1':
      num.value += '1';
      break;
    case '2':
      num.value += '2';
      break;
    case '3':
      num.value += '3';
      break;
    case '4':
      num.value += '4';
      break;
    case '5':
      num.value += '5';
      break;
    case '6':
      num.value += '6';
      break;
    case '7':
      num.value += '7';
      break;
    case '8':
      num.value += '8';
      break;
    case '9':
      num.value += '9';
      break;
    case '0':
      num.value += '0';
      break;
    case '.':
      num.value += '.';
      break;
  }
})

let opbutt = document.querySelector('.ver-op');
opbutt.addEventListener('click', (event) => {
  let target = event.target;
  switch (target.value) {
    case '*':
      firstnum = num.value;
      operand = '*';
      memory.textContent = firstnum + operand;
      num.value = '';
      break;
    case '-':
      firstnum = num.value;
      operand = '-';
      memory.textContent = firstnum + operand;
      num.value = '';
      break;
    case '+':
      firstnum = num.value;
      operand = '+';
      memory.textContent = firstnum + operand;
      num.value = '';
      break;
    case '/':
      firstnum = num.value;
      operand = '/';
      memory.textContent = firstnum + operand;
      num.value = '';
      break;
  }
})

let eq = document.querySelector('.equal');
eq.addEventListener('click', (event) => {
  secnum = num.value;
  result = 0;
  memory.textContent = (firstnum) + operand + (secnum);
  if (operand == '/') {
    result = Number(firstnum) / Number(secnum);
    num.value = num.value.toFixed(2);
  } else if (operand == '*') {
    result = Number(firstnum) * Number(secnum);
  } else if (operand == '+') {
    result = Number(firstnum) + Number(secnum);
  } else if (operand == '-') {
    result = Number(firstnum) - Number(secnum);
  }
  num.value = result;
  
  firstnum = result;
})

let clear = document.querySelector('.clearbutt');
clear.addEventListener('click', (event) => {
  firstnum = '';
  secnum = '';
  operand = '';
  num.value = '';
  memory.textContent = '';
})

let calckey = document.getElementById('calc-container');
calckey.addEventListener('keypress', (event) => {
  if (event.key === 'Enter') {
    secnum = num.value;
    result = 0;
    if (operand === '/') {
      result = Number(firstnum) / Number(secnum);
    } else if (operand === '*') {
      result = Number(firstnum) * Number(secnum);
    } else if (operand === '+') {
      result = Number(firstnum) + Number(secnum);
    } else if (operand === '-') {
      result = Number(firstnum) - Number(secnum);
    }
    num.value = result;
    memory.textContent = (firstnum) + operand + (secnum);
    firstnum = result;
  }
})
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>online-calculator</title>
  <link rel="stylesheet" href="/style.css">
  <script src="/calculator.js" defer></script>
</head>

<body>
  <div id="calc-container">
    <div id="calulation">
      <p id="memory"></p>
      <input type="text" name="inptext" class="inp" id="inp-num" readonly>
    </div>
    <div id="hor-op">
      <div class="left-side">
        <button class="horop-but">%</button>
        <button class="horop-but">CE</button>
        <button class="horop-but clearbutt">C</button>
        <button class="horop-but"><sup>1 </sup> / <sub>x</sub></button>
        <button class="horop-but">x<sup>2</sup></button>
        <button class="horop-but">โˆš</button>
      </div>
      <div class="right-side">
        <button class="horop-right-but " value="cls"><img src="/icons8-rewind-button-round-50.png" alt=""></button>
        <button class="horop-right-but equal" value="=">=</button>
      </div>


    </div>
    <div id="main">
      <div id="numbers">
        <button class="butt num-but" value="1">1</button>
        <button class="butt num-but" value="2">2</button>
        <button class="butt num-but" value="3">3</button>
        <button class="butt num-but" value="4">4</button>
        <button class="butt num-but" value="5">5</button>
        <button class="butt num-but" value="6">6</button>
        <button class="butt num-but" value="7">7</button>
        <button class="butt num-but" value="8">8</button>
        <button class="butt num-but" value="9">9</button>
        <button class="num-but">+/-</button>
        <button class="butt num-but" value="0">0</button>
        <button class="butt num-but" value=".">.</button>
      </div>
      <div class="ver-op">
        <button class="verop-but " value="*">*</button>
        <button class="verop-but " value="-">-</button>
        <button class="verop-but " value="+">+</button>
        <button class="verop-but " value="/">/</button>
      </div>
    </div>
  </div>
</body>

</html>

for example : 8 * 5 =40 but my result is 405.second number is joining my result number.
it happens just when i am using keypress event.
while i am using by click event it is working

My site is not eligible for PayPal JS SDK

I’m writing a nextjs app, currently debugging it on localhost.
I want to have inputs for card details using PayPal JS SDK, so I just the card-fields component.

However cardFields.isEligible() returns false. If I tried to render the NameField any I get an exception clientID prop not defined. I’m using a sandbox app id.

Here’s the react component

export default function PayPalClient() {
  const onScriptLoad = () => {
    const cardFields = window.paypal.CardFields({});

    if (cardFields.isEligible()) {
      cardFields.NameField().render(document.getElementById("card-name-field-container"));
    }
    else {
      console.log('not eligible');
    }
  }

  return (
    <div>
      <Script
        src={`https://www.paypal.com/sdk/js?client-id=${CLIENT_ID}&components=card-fields`}
        strategy="afterInteractive"
        crossOrigin="anonymous"
        onLoad={onScriptLoad}
      />
      {/* Testing just the card name field right now */}
      <div id="card-name-field-container" />
    </div>
  );
}

What am I doing wrong?

Why do I need to select an option from this ReactJS drop-down menu twice for the change to register?

I am working with an application that has a Java backend, utilising the Play Framework, and a ReactJS frontend. One of the pages contains a form where user data can be edited and it has a drop-down menu whose values are populated from the backend, based on that userโ€™s database information. Letโ€™s imagine the three values in range are Employed, Unemployed, Temporarily_Employed. If a user is in the system as Employed then that should be selected as the default in the drop-down menu.

The problem I am experiencing is that, when first interacting with the drop-down, even if I choose another option from the list (eg: Unemployed) the change is not registered and the default option is still selected. This does not happen if I select from the drop-down a second or further time – it works fine then.

<FormSelect
    id="employmentStatus"
    name="theName"
    label="theLabel"
    options= // the statuses in range, eg: Employed, etc
    selected={this.state.employmentStatus} //This seems to be where the trouble begins - I populate it initially with whatever the appropriate value is in the user's record in the DB
    onChange={this.handleEmploymentStatusChange}
    hasEmptyDefault={!this.state.employmentStatus}
/>


export default class EmploymentStatusPage extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            name,
            email, 
            employmentStatus
        }
    }
}

handleEmploymentStatusChange = newValue => {
    this.setState({
        employmentStatus: newValue
    })
}

In Angular, a awaited method call, kicks you out of the NgZone. Why?

When you do a simple call like await Promise.resolve() inside an Angular component, the code below that call will not be inside the zone anymore.

The easiest way to reproduce this is to create a component and write this into any method:

console.log('Inside Angular zone?', NgZone.isInAngularZone()); // => true
await Promise.resolve();
console.log('Inside Angular zone?', NgZone.isInAngularZone()); // => false

(Done in this stackblitz)

Why is that the case?

As long as i don’t use e.g. zone.runOutsideAngular() i don’t expect to be kicked out.

How to display a .gexv file on a website using sigma.js

so maybe this is the most easy question ever, but I’m reading the documentation for days now and I still don’t have a clue.

I want to display a .gexf file stored on my server on the website that’s on that server.

I managed running a sigma.js script, but not an external file like here: https://www.sigmajs.org/storybook/?path=%2Fstory%2Fload-gexf-file–story

Maybe I just don’t know how to set the file path, but actually, I’m lost.

Thanks

WordPress assets loading. Uncaught TypeError: Failed to resolve module specifier

I hope you can help me with one, it’s drivinig me crazy ๐Ÿ™

I recently splitted a giant file called admin.js into many modules, using these two WordPress functions:

So, every module is mapped by an importmap, like this:

<script type=""importmap""id=""wp-importmap"">"{
   "imports":{
      "admin_colorpicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_colorpicker.min.js?ver=6.8.3",
      "admin_commons_js":"/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_commons.min.js?ver=6.8.3",
      "admin_datepicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_datepicker.min.js?ver=6.8.3",
      "admin_editor_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_editor.min.js?ver=6.8.3",
      "admin_file_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_file.min.js?ver=6.8.3",
      "admin_flexible_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_flexible.min.js?ver=6.8.3",
      "admin_helpers_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_helpers.min.js?ver=6.8.3",
      "admin_iconpicker_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_iconpicker.min.js?ver=6.8.3",
      "admin_list_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_list.min.js?ver=6.8.3",
      "admin_misc_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_misc.min.js?ver=6.8.3",
      "admin_relational_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_relational.min.js?ver=6.8.3",
      "admin_repeater_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_repeater.min.js?ver=6.8.3",
      "admin_sortable_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_sortable.min.js?ver=6.8.3",
      "admin_woocommerce_js":"https://******/wp-content/plugins/advanced-custom-post-type/assets/static/js/_admin_woocommerce.min.js?ver=6.8.3"
   }
}"</script>

In rare cases, my clients got this error from the browser:

Uncaught TypeError: Failed to resolve module specifier "admin_commons_js". Relative references must start with either "/", "./", or "../".

There’s no way to reproduce the issue on my localend/staging enviroment.

By the way, the admin.js is called AFTER the importmap.

Can anyone explain that and how to fix it?

Thanks in advance to everyone ๐Ÿ™‚

M

I tried to reproduce the issue on my end, no luck.

Form Submit needs to wait for any ongoing Blur fetch from a field

In my React application one of the Form fields is zipCode which On Blur will populate city and state via a ZipCode-based API fetch.

valueMapChange is a mutator of the Form state-variable map valueMapMap<string, any>().

    <TextInput id="zipCode"
               onChange={(e) => valueMapChange("zipCode", e.target.value.replace(/D/g, ""))}
               onBlur={(e) => { handleZipBlur(e.target.value) }}
               ... />

    const handleZipBlur = (value: string) => {
        fetchCityState(value); // On BLUR populate 'city' and 'state'
    }

    const fetchCityState = async (zipcode: string) => {
        //...Preliminary validation
        // API fetch
        const response = await getCityState<any>(zipcode);
        if (!response.errorMessage) {
                valueMapChange('city', response.city);
                valueMapChange('state', response.state);
        }
    }

There is also a Form Submit button that submits the form. If the user is in the Zip field and clicks Submit, sometimes there’s a race condition where it doesn’t have enough time to set the City/State into the valueMap, so the submit goes in without the City/State values.

The Submit function itself shouldn’t be async because it doesn’t require anything. It doesn’t need to specifically wait for something. But it needs to detect whether an optional OnBlur City/State fetch is currently ongoing, and if so wait for that fetch. What’s the best way to implement this?

Diffrence between extending http.Server vs. http.createServer

I want to create a custom HTTP server instance, with custom methods.

The first try was to extend http.createServer(), but this fails because I can’t access my custom methods.

const {createServer, Server} = require("http");


class Direct extends Server {

    constructor(...args){
        super(...args);
    }

    foo(){
        console.log("foo");
        return "foo";
    }

}


class Wrapper extends createServer {

    constructor(...args){
        super(...args);
    }

    foo(){
        console.log("foo");
        return "foo";
    }

}


const direct = new Direct();
const wrapper = new Wrapper();


[direct, wrapper].forEach((server, i) => {

    server.once("request", (req, res) => {
        server.foo();
        res.end(`Hello from server ${i}`);        
    });

    server.listen(9000 + i, () => {
        console.log(`Server #${i} listening on port ${9000 + i}`);
    });

});

Output:

Server #0 listening on port 9000
Server #1 listening on port 9001
foo
/tmp/server.js:39
        server.foo();
               ^

TypeError: server.foo is not a function
    at Server.<anonymous> (/tmp/server.js:39:16)
    at Object.onceWrapper (node:events:633:26)
    at Server.emit (node:events:518:28)
    at parserOnIncoming (node:_http_server:1153:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)

Node.js v22.16.0
curl -v http://127.0.0.1:9000
curl -v http://127.0.0.1:9001

As soon as the “Wrapper” server hits a request:

TypeError: server.foo is not a function
    at Server.<anonymous> (/tmp/server.js:39:16)
    at Object.onceWrapper (node:events:633:26)
    at Server.emit (node:events:518:28)
    at parserOnIncoming (node:_http_server:1153:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:117:17)

Node.js v22.16.0

The request to the “Direct” server/class works as expected.

What’s the difference between both extending approaches above, when both http.createServer() & http.Server return an HTTP server instance?

How to handle Chrome autoplay policy in a call center web application?

Context

I’m developing a web-based call center application where agents receive incoming calls through the browser. When a call comes in, the application needs to play a ringtone to alert the agent.

Problem

Chrome’s autoplay policy is blocking the ringtone from playing automatically when an incoming call arrives. According to Chrome’s autoplay documentation, audio can only play after a user interaction.
However, in a call center context:

  • Agents may be idle when a call arrives
  • The ringtone must play immediately without requiring the agent to click something first
    This is mission-critical functionality
  • agents cannot miss incoming calls

Questions

What is the recommended approach for implementing call ringtones in web-based telephony applications given Chrome’s autoplay restrictions?

Environment:

Chrome 120+
Vanilla JavaScript (can use modern APIs)
WebRTC for call signaling

EDIT

Why This is Different from General Autoplay Questions

I’ve read the existing questions about Chrome’s autoplay policy, including this one about Chrome 76, but my situation has specific constraints:

  1. No predictable user interaction – In a call center, calls arrive randomly when agents may be idle or working on post-call tasks. We cannot require a click “just before” each call.

  2. Mission-critical audio – Unlike media websites where autoplay is a convenience, missing a ringtone means missing a customer call, which has business consequences.

  3. Long-running sessions – Agents log in once at the start of their shift (could be 4-8 hours). I need to know if a single interaction at session start is sufficient to enable audio for the entire shift.

  4. Multiple audio sources – We need ringtones, notification sounds, and potentially call audio. Do these all count as separate autoplay contexts?

Specific question: Is there a reliable pattern for “unlocking” audio permissions at session start that will persist for hours and work across all major browsers for a telephony application?

Puppeteer/Jest test for Firebase extension times out waiting for Firestore document created by onUserCreate Cloud Function

I am testing a Chrome extension (Manifest V3) using Jest and Puppeteer. The extension uses Firebase Authentication and Firestore.

The Goal:
My test needs to register a new user, wait for a backend Cloud Function to create their profile document in Firestore, and then perform actions as that user.

The Problem:
My onUserCreate Cloud Function runs successfully when a user is registered (I have verified this manually and by checking the Firestore database โ€“ the /Users/{uid} document is created correctly).

However, my test script’s polling loop, which repeatedly calls a getUserProfile function to check for this document, consistently fails to find it and eventually times out.

Why would a client-side .get() request from within a Puppeteer test fail to find a document that was successfully created by a Cloud Function moments before? Could this be a Firestore consistency issue that is specific to a test environment, or a problem with how auth state is handled by the client SDK in this context?

I have confirmed that billing is enabled for my Google Cloud project and the project is on the Blaze plan.

I have already tried implementing a polling loop to wait for the document, as suggested in similar questions, but the test still times out.

Here is the relevant code:

  1. The Cloud Function (functions/index.js):
exports.initializeNewUser = functions.auth.user().onCreate(async (user) => {
  const db = admin.firestore();
  const settingsDoc = await db.collection("settings").doc("trustScoreRules").get();
  const initialScore = settingsDoc.exists ? settingsDoc.data().initialScoreTom : 3;
  const newUserProfile = {
    email: user.email,
    trustScore: initialScore,
    // ... other fields
  };
  return db.collection("Users").doc(user.uid).set(newUserProfile);
});
  1. The Test Script Polling Logic (tests/extension.test.js):
// This happens inside a beforeAll block
// ... after user is successfully registered and signed in ...

let userProfile = null;
for (let i = 0; i < 10; i++) {
  const response = await worker.evaluate(async () => {
    return new Promise((resolve) => {
      chrome.runtime.sendMessage(
        { type: 'getUserProfile', target: 'background' },
        (response) => { resolve(response); }
      );
    });
  });
  if (response && response.success) {
    userProfile = response.profile;
    break;
  }
  await new Promise(resolve => setTimeout(resolve, 1000));
}
if (!userProfile) {
  throw new Error("Timed out waiting for user profile to be created...");
}
  1. The Client-Side Fetch Logic (offscreen.js):
case 'getUserProfile': {
    const unsubscribe = auth.onAuthStateChanged(user => {
        unsubscribe();
        if (user) {
            db.collection('Users').doc(user.uid).get()
                .then(doc => {
                    if (doc.exists) {
                        sendResponse({ success: true, profile: doc.data() });
                    } else {
                        sendResponse({ success: false, error: "User profile not found." });
                    }
                })
        } else {
             sendResponse({ success: false, error: "User not authenticated." });
        }
    });
    return true;
}

The result was that the New User was indeed created in Firestore and Firebase Authentication, but it is failing two of the three tests. Here is the terminal output:



> [email protected] test
> NODE_OPTIONS=--experimental-vm-modules jest

(node:2283) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 FAIL  tests/extension.test.js (12.447 s)
  Anotato Extension Tests
    Extension Loading
      โœ“ should load the extension and find the service worker (2 ms)
    User Actions
      โœ• should show a signed-in state in the popup
      โœ• should allow a signed-in user to create an annotation

  โ— Anotato Extension Tests โ€บ User Actions โ€บ should show a signed-in state in the popup

    Timed out waiting for user profile to be created by Cloud Function.

      83 |       }
      84 |       if (!userProfile) {
    > 85 |         throw new Error("Timed out waiting for user profile to be created by Cloud Function.");
         |               ^
      86 |       }
      87 |     });
      88 |

      at Object.<anonymous> (tests/extension.test.js:85:15)

  โ— Anotato Extension Tests โ€บ User Actions โ€บ should allow a signed-in user to create an annotation

    Timed out waiting for user profile to be created by Cloud Function.

      83 |       }
      84 |       if (!userProfile) {
    > 85 |         throw new Error("Timed out waiting for user profile to be created by Cloud Function.");
         |               ^
      86 |       }
      87 |     });
      88 |

      at Object.<anonymous> (tests/extension.test.js:85:15)

Test Suites: 1 failed, 1 total
Tests:       2 failed, 1 passed, 3 total
Snapshots:   0 total
Time:        14.223 s
Ran all test suites.

Using PSD.js, how to output png as buffer?

In a Nodejs project, I am using PSD.js to generate a png from a psd. I am using the .toPng() method. I would like to go from this png object to a buffer without saving to the file system. I have tried Buffer.from(png) and I have tried using Sharp’s sharp(png).toBuffer() without luck. Sharp is then used to modify the png buffer.

const psd = new PSD(fileBuffer);
psd.parse();

if (!psd.image) {
    throw 'Error message';
}
const png = psd.image.toPng();
convBuffer = Buffer.from(png); 
             //await sharp(png).toBuffer() failed 
             //await png.get() failed

What is the global object inside a module in Node.js?

When I execute this code from the Node.js console, the function Foo can be found in the globalThis object ([Function: Foo]):

function Foo () { console.log ("Hello world!"); }
console.log (globalThis["Foo"]);

When I put this code in a module foo.mjs and run the code with the command line “node.js foo.mjs”, the Foo function cannot be found in globalThis.

From inside a module, what is the global object that contains the functions and variables defined in this module?