Is it possible to create an abstract type and make it compatible for inheritance into child type?

Let’s say I have an abstract type and function like this.

type GenericData = {
    id: string
}

export const recv = ( data: GenericData, properties: Props ): GenericData =>
{
    return {
        id,
        ...properties
    }
}

And I want to load this data into more specific types which inherit from the generic type and add to it.

type SpecificData = GenericData & {
    name: string,
    phone: number
}

const specific: SpecificData = recv( inputData, props );

Now it shows a TypeScript error that SpecificData and GenericData are not compatible.

How do I create multiple implementations of this generic type when different data is received?

The problem with playing tracks and playlists from vkontakte to Discord

So, my test bot Discord is playing something, but it is silent and does not come out of the voice, I do not understand what is wrong with the code, although there are no errors and User_agent added I would like any help I would be very grateful

const { MessageEmbed, Permissions } = require('discord.js');
const { convertTime } = require('../../utils/convert.js');
const axios = require('axios');
const { access } = require('fs');


const USER_AGENT = 'VKAndroidApp/5.8.1 (Android 9.0; Transsion; RMA1852C; zh_CN; 1080x2340; 32bit; vk.com/app318634226)';
const VK_API_METHOD_BASE_URL = 'https://api.vk.com/method/';
const VK_API_VERSION = '5.87'; // Обязательно укажите актуальную версию API
const ACCESS_TOKEN = ''; // Токен, который вы получите после авторизации аккаунта vk
const axiosInstance = axios.create({
  headers: {
    'User-Agent': USER_AGENT,
  },
});

async function getMp3FromM3u8(url) {
  // Not a m3u8 url
  if (!url.includes('index.m3u8?')) {
    return url;
  }

  const match = url.match(/^(.+?)/(audio|(p[0-9]+)/)?([^/]+)/);
  if (match[2]) {
    return `${match[1]}/audio${match[4]}.mp3`;
  }
  return `${match[1]}/${match[3]}/${match[4]}.mp3`;
}


// **Используйте async/await для обработки асинхронных операций:**

async function searchVkTracks(query) {
  const response = await axiosInstance.get(`${VK_API_METHOD_BASE_URL}audio.search`, {
    params: {
      q: query,
      access_token: ACCESS_TOKEN,
      v: VK_API_VERSION,
    },
  });
  const data = response.data;

  if (data.error) {
    throw new Error(`Ошибка API ВКонтакте: ${data.error.error_msg}`);
  }

  return data.response?.items || [];
}

async function getVkTrackInfo(trackId) {
  const response = await axiosInstance.get(`${VK_API_METHOD_BASE_URL}audio.getById`, {
    params: {
      audio_ids: trackId,
      access_token: ACCESS_TOKEN,
      v: VK_API_VERSION,
    },
  });
  

  const data = response.data;

  if (data.error) {
    throw new Error(`VK API Error: ${data.error.error_msg}`);
  }

  return data.response?.items[0] || null;
}


module.exports = {
  name: 'vkplay',
  category: 'Music',
  aliases: ['vp'],
  description: 'Воспроизводит аудио или плейлист с VK.com ',
  args: true,
  usage: '<VK TRACK URL | VK Playlist URL | VK TRACK NAME>',
  userPrams: [],
  botPrams: ['EMBED_LINKS'],
  owner: false,
  inVoiceChannel: true,
  sameVoiceChannel: true,
  execute: async (message, args, client, prefix) => {
    if (!message.guild.members.me.permissions.has([Permissions.FLAGS.CONNECT, Permissions.FLAGS.SPEAK])) {
      return message.channel.send({
        embeds: [
          new MessageEmbed()
            .setColor(client.embedColor)
            .setDescription('У меня недостаточно прав для выполнения этой команды! Пожалуйста, предоставьте мне разрешения `CONNECT` и `SPEAK`.')
        ],
      });
    }

    const emojiAddSong = message.client.emoji.addsong;
    const emojiPlaylist = message.client.emoji.playlist;

    const { channel } = message.member.voice;

    if (!message.guild.members.me.permissionsIn(channel).has([Permissions.FLAGS.CONNECT, Permissions.FLAGS.SPEAK])) {
      return message.channel.send({
        embeds: [
          new MessageEmbed()
            .setColor(client.embedColor)
            .setDescription('У меня недостаточно прав на подключение к вашему голосовому каналу. Пожалуйста, предоставьте мне разрешения `CONNECT` и `SPEAK`.')
        ],
      });
    }

    const query = args.join(' ');

    const player = await client.manager.createPlayer({
      guildId: message.guild.id,
      voiceId: message.member.voice.channel.id,
      textId: message.channel.id,
      deaf: true,
    });

    // **Определите тип запроса:**

    let tracks = [];

if (isVkTrackUrl(query)) {
  // **Получить информацию о треке:**
  const trackInfo = await getVkTrackInfo(parseVkTrackIdFromUrl(query));

  if (!trackInfo) {
    return message.reply('Трек не найден.');
  }

  tracks.push(trackInfo);
} else if (isVkPlaylistUrl(query)) {
  // **Получить список треков из плейлиста:**
  const playlistTracks = await getVkPlaylistTracks(parseVkPlaylistIdFromUrl(query));

  if (!playlistTracks.length) {
    return message.reply('Плейлист пуст.');
  }

  tracks = playlistTracks;
} else {
  // **Поиск треков по имени:**
  tracks = await searchVkTracks(query);

  if (!tracks.length) {
    return message.reply('Трек не найден.');
  }
}

// **Добавить треки в очередь:**

if (tracks.length > 1) {
  const uniqueTracks = [...new Set(tracks)]; // Remove duplicate tracks

  for (const track of uniqueTracks) {
    player.queue.add(track);
  }

  return message.reply({
    embeds: [
      new MessageEmbed()
        .setColor(client.embedColor)
        .setDescription(`${emojiPlaylist} В очередь добавлено ${uniqueTracks.length} уникальных треков`)
    ],
  });
} else {
  player.queue.add(tracks[0]);

  return message.reply({
    embeds: [
      new MessageEmbed()
        .setColor(client.embedColor)
        .setDescription(`${emojiAddSong} В очереди [${tracks[0].title}](${tracks[0].url})`)
    ],
  });
}

  
  }, 
};

// **Функции для проверки URL:**

function isVkTrackUrl(url) {
  return /https://vk.com/audio(d+)(_d+)?/.test(url);
}

function isVkPlaylistUrl(url) {
  return /https://vk.com/album/(-d+)_(d+)_(d+)/.test(url);
}

// **Функции для парсинга URL:**

function parseVkTrackIdFromUrl(url) {
  const match = /https://vk.com/audio(d+)(_d+)?/.exec(url);
  return parseInt(match[1]);
}

function parseVkPlaylistIdFromUrl(url) {
  const match = /https://vk.com/album/(-d+)_(d+)_(d+)/.exec(url);
  return parseInt(match[1]);
}

// **Дополнительные функции:**

async function getVkPlaylistTracks(playlistId) {
  // ... код для получения списка треков из плейлиста ...
}

The screen console

Discord screen

the link that it gives out: https://vk.com/mp3/audio_api_unavailable.mp3

I tried many options and it didn’t help, but there are no errors

Page is blank after I reload it even tho the navbar stays there + i’m still logged in

See the result here : (https://i.stack.imgur.com/dZY3K.png)

I stay logged in but when I put my mouse on the name there isn’t anything (it is supposed to show the “log out” option).

And also the page is empty even tho it is supposed to say “Welcome”.

When I log from the login page everything is fine but as soon as I reload once, it goes like the screen shot

It happened when I tried to only keep the token in the local+session storage, because before I was keeping all of the user data in there.

how to draw the magnetic field of lines around a bar magnet

I searched for various options to draw magnetic field lines around the bar like the image attached here but didn’t find any solutions. Any guidance on how to achieve this? A user should also be able to rotate the bar magnet using input text values or mouse values. I am from a science background so I can learn once I know which direction I should be looking for.

Magnet Image user view

I tried using vpython and p5.js but I couldn’t get the problem solved using them.

jQuery – Targeting a checkbox with a value containing double quotes

I am attempting to pre-populate a form which has inputs with values I am not able to change. One of the fields is a series of checkboxes and some of the values contain double quotes to represnt inches. I have an array of values I want to change to checked but I’m not sure how to target those inputs with values containing double quotes.

let sizeArr = ['short', 'under 28"', 'over 28"'];
sizeArr.forEach(function(val) {
    console.log(val);
    $(':checkbox[value='+ val +']').prop('checked', 'true');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<label>
  Short
  <input type="checkbox" value="short" />
</label>

<label>
  Under 28"
  <input type="checkbox" value="under 28&quot;">
</label>

<label>
  Over 28"
  <input type="checkbox" value="over 28&quot;">
</label>

I also tried replacing the double quotes with &quot; directly in the array, but the selector still doesn’t seem to work:

let sizeArr = ['short', 'under 28&quot;', 'over 28&quot;'];
sizeArr.forEach(function(val) {
    console.log(val);
    $(':checkbox[value='+ val +']').prop('checked', 'true');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<label>
  Short
  <input type="checkbox" value="short" />
</label>

<label>
  Under 28"
  <input type="checkbox" value="under 28&quot;">
</label>

<label>
  Over 28"
  <input type="checkbox" value="over 28&quot;">
</label>

Elements inside of dialog element will not show up when outside of bounds of dialog

Problem

Wanted to create a dialog element that has an x button to close the <dialog> in the top-right. I was thinking I could use absolute position / transforms to accomplish it, but when the x button reaches outside of bounds, the part of it that is outside the parent <dialog> is not visible.

const openDialog = document.querySelector("#open-dialog")
const closeDialog = document.querySelector("#close-dialog")
const dialog = document.querySelector("dialog")

openDialog.addEventListener("click", () => {
  dialog.showModal();
})
closeDialog.addEventListener("click", () => {
  dialog.close();
})
html {
  height: 100%;
  width: 100%;
}

dialog {
  position: relative;
  height: 50px;
}

#close-dialog {
  position: absolute;
  background-color: pink;
  top: -10px;
  z-index: 1;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>replit</title>
  <link href="style.css" rel="stylesheet" type="text/css" />
</head>

<body>
  <button id="open-dialog">Open dialog</button>
  <dialog>
    <buton id="close-dialog">x</buton>
  </dialog>
  <script src="script.js"></script>
</body>

</html>

Results

When I add top: -10px, it shifts the #close-dialog button up, and now only a part of it can actually be seen. The other part is fully hidden.

Tried:

  • Using z-index, didn’t work
  • Using transform: translateY(), didn’t work

Expected:

  • The #close-dialog should not be hidden

why am i getting undefined when returning a value

so I keep getting undifinded when trying to get just one number to return. what am I doing wrong?

const megaball = () =>{
  
    let random_number
 while(true){
    random_number = math.floor(math.random() * 100)
    console.log(random_number)
    if(random_number <= 25 && random_number !== 0) {
        console.log('break')
        break
    }
 }
 return random_number
}

the results from this function are as follows:

55
67
17
break
17
undefined
PS C:UsersdallaOneDriveDocumentslottery>  

I need to know why I am getting undefined when i am suppose to be just returning the 17 as the random number.

How do I format my secondary axis line values as percent using Google Chart API JavaScript

My chart consists of 2 stacked bars on the primary vertical axis and a line on the secondary axis. My secondary vAxis is formatted as % and displays as I want, however, the individual datapoints display as decimal values, i.e., -0.446, and what I would like is -44.6%.

Chart sample showing format to fix

JavaScript code

 <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
 <script type="text/javascript">

     google.charts.load('current', { packages: ['corechart'] });
     google.charts.setOnLoadCallback(drawChart);

     function drawChart() {
         var data = new google.visualization.DataTable();

         var jsonList = @(Json.Serialize(Model.listAllAircraftChart))

         var title = 'Monthly Aircraft Transaction Trend';

         data.addColumn('string', 'Month');
         data.addColumn('number', '2024');
         data.addColumn('number', '2023');
         data.addColumn('number', '% Change');
         data.addRows(jsonList.map((p) => {
             return [p.yearMonth, p.year1top, p.year2bottom, p.year1percent];
         }));

         var view = new google.visualization.DataView(data);
         view.setColumns([0, 1,
             {
                 calc: "stringify",
                 sourceColumn: 1,
                 type: "string",
                 role: "annotation"
             },
             2,
             {
                 calc: "stringify",
                 sourceColumn: 2,
                 type: "string",
                 role: "annotation"
             },
             3,
             {
                 calc: "stringify",
                 sourceColumn: 3,
                 type: "string",
                 role: "annotation"
             }

         ]);
         var options = {
             title: title,
             titlePosition: 'out',
             isStacked: true,

             seriesType: "bars",
             vAxes: {
                 0: {
                     textPosition: 'out',
                     viewWindowMode: 'pretty',
                     viewWindow: { min: -750, max: 750 },
                     gridlines: { color: 'light-gray' },
                 },
                 1: {
                     textPosition: 'out',
                     viewWindow: { min: -1, max: 1 },
                     format: 'percent',
                     gridlines: { color: 'transparent' }
                 },
             },
             series: {
                 0: { targetAxisIndex: 0, color: 'blue'},
                 1: { targetAxisIndex: 0, color: 'gray' },
                 2: { targetAxisIndex: 1, color: 'red', type: 'line', lineWidth: 1, lineDashStyle: [4, 4], pointSize: 5 },
             },
             width: '100%',
             height: '300',

             legend: { position: 'top' },
             chartArea: {
                 height: '100%',
                 width: '100%',
                 top: 48,
                 left: 60,
                 right: 60,
                 bottom: 75
             },
             annotations: {
                 textStyle: {
                     color: 'black',
                     fontSize: 11,
                 },
                 alwaysOutside: true
             },
         }

         var chart = new google.visualization.ComboChart(document.getElementById('primaryCurrentYear'));
         chart.draw(view, options);

         document.getElementById('downloadimg').innerHTML = '<a download="google-chart-image" href="' + chart.getImageURI() +
             '"><button type="button" class="btn btn-outline-dark btn-sm opacity-25 ms-4 mb-3">Download Chart Image</button></a>';

         window.addEventListener('resize', drawChart, false);
     }
 </script>

I have tried researching similar charts and reviewed Google Charts API documentation, but I haven’t been able to figure it out.

EventListener not working properly even though elements are populating correctly

I’m having trouble with the event listeners within the for loop. Currently, I have the buttons and everything showing up on my page properly. I’m suspecting it may be an issue with the for loop, I cant figure this out since I did something similar on a different project that worked.

function generateProjectElements(information) {
  let projectContainer = document.createElement("div");

  for (let x = 0; x < information.length; x++) {
    let projectDiv = document.createElement("div");
    let projectName = document.createElement("h3");
    let buttonsDiv = document.createElement("div");
    let editButton = document.createElement("button");
    let deleteButton = document.createElement("button");

    projectDiv.setAttribute("data-index", x);

    projectDiv.className = "side-project-div";
    buttonsDiv.className = "side-project-btns";
    editButton.className = "edit-btn";
    deleteButton.className = "delete-btn";
    projectName.innerText = information[x];


    editButton.addEventListener("click", () => {
      console.log("Hi")
    });

    deleteButton.addEventListener("click", () => {
      console.log("Delete!")
    })
    
    projectDiv.appendChild(projectName);
    buttonsDiv.appendChild(editButton);
    buttonsDiv.appendChild(deleteButton);
    projectDiv.appendChild(buttonsDiv);
    
    projectContainer.appendChild(projectDiv);
  }

  return projectContainer.innerHTML;
}


function updateSideMenu(projectArray) {
  let projectCont = document.querySelector(".project-container")
  
  projectCont.innerHTML = generateProjectElements(projectArray)
}

When I click them (editButton and deleteButton), its not printing anything out to console.

Can someone please help me?

merge two arrays by matching on different columns where arrays are of unequal length unequal length

I am trying to merge two arrays on columns with similar data

I can get this to work if both arrays have the same length dimension, but how can I generalize my function to work if arrays have different lengths?

where either arrA or arrB could have the greater length

Thank you

what I get

[ [ 'age', 'AAA', 'name' ],
  [ 25, 'aaa', 'Alice' ],
  [ 30, 'bbb', 'Bob' ] ]

what I want

[
  [ 'age', 'AAA', 'name' ],
  [ 25, 'aaa', 'Alice' ],
  [ 30, 'bbb', 'Bob' ],
  [ 60, 'zzz', '' ] 
]
function mergeRowsLOOP_n() {
  const arrB = [
  ["id", "name"],
  [1, "Alice"],
  [2, "Bob"],
];

const arrA = [
  ["age","ID", "AAA"],
  [25, 1, "aaa"],
  [30, 2, "bbb"],
  [60, 5, "zzz"]
];

let X = mergeRowsLOOP(arrA, arrB, "ID", "id");
console.log(X)
}

//a= array1, b=array2
//aKey = Header for Matching of arra1, bKey = Header for Matching of arra2
//bColumns indices of postback columns of array2; bColumns=[] to postback ALL array2 columns
function mergeRowsLOOP(a, b, aKey, bKey, bColumns=[]) {
  
  const  bIdx = b[0].findIndex(s => s.toLowerCase() === bKey.toLowerCase());
  bColumns= (bColumns.length===0) ? b : getColumns(b, [bIdx,...bColumns]);

  const aIdx        = a[0].findIndex(s => s.toLowerCase() === aKey.toLowerCase()),
        bColumnsIdx = bColumns[0].findIndex(s => s.toLowerCase() === bKey.toLowerCase()),
        mergedArray = [];     
console.log(bColumnsIdx)
  for (let rowA of a) {
    for (let rowB of bColumns) {
      if (rowA[aIdx].toString().toLowerCase() === rowB[bColumnsIdx].toString().toLowerCase()) {
        rowA = spliceNthPos(rowA,aIdx);
        rowB = spliceNthPos(rowB,bColumnsIdx);
        mergedArray.push(rowA.concat(rowB,));
      }
    }
  };

return mergedArray;
}
function spliceNthPos(row, n){
let i = row.length;
while (i--) {
  i === n && row.splice(i, 1);
 }
 return row;
}

Error in Cordova: Uncaught TypeError: Cannot read properties of undefined (reading ‘_cordovaNative’

I am developing a hybrid app with Cordova, and when I launch it using Android Studio, I encounter the following error in the console:

Uncaught TypeError: Cannot read properties of undefined (reading '_cordovaNative')
    at cordova.js:340:22
    at build (cordova.js:47:9)
    at require (cordova.js:62:24)
    at localRequire (cordova.js:43:20)
    at cordova.js:932:25
    at build (cordova.js:47:9)
    at require (cordova.js:62:24)
    at localRequire (cordova.js:43:20)
    at Object.bootstrap (cordova.js:1420:20)
    at cordova.js:1281:32

```
`
When i do Cordova run browser it works perfect, but not with cordova run android. 

TON transfer bug when using 32 (DESTROY_ACCOUNT_IF_ZERO) flag?

I’ve been trying to reuse a wallet deleted by DESTROY_ACCOUNT_IF_ZERO (32) flag. The way I do the transfer:

Imagine we have 2 wallets: A and B.

  1. We transfer N1 TON from A to B. E.g. by using a web-based wallet, script, doesn’t matter.
  2. B is uninitialized – it is not on the blockchain yet. With that in mind, we’d like to send all the money from B back to A. For this we’re going to use the attached script.
  3. Now we go ahead and transfer N2 TON from A to B again. Doesn’t matter how much.

Expected behavior: we get transactions: A->B (N1), B->A (all), A->B (N2); wallet B has N2 TONs in the end.

Actual behavior: we get transactions A->B (N1), B->A (all), A->B (N2), B->A (all); wallet B has 0 TONs in the end.

The script for B->A (all) transfer, which causes this behavior:

import TonWeb from 'tonweb';
import tonwebMnemonic from 'tonweb-mnemonic';


const apiKey = "" || undefined;
// WALLET B
const mnemonic = "...";
const walletVersion = "v4R2";
// WALLET A
const toAddress = "...";


const SendMode = {
    CARRY_ALL_REMAINING_BALANCE: 128,
    CARRY_ALL_REMAINING_INCOMING_VALUE: 64,
    DESTROY_ACCOUNT_IF_ZERO: 32,
    PAY_GAS_SEPARATELY: 1,
    IGNORE_ERRORS: 2,
    NONE: 0
}

const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));


(async () => {
    const provider = new TonWeb.HttpProvider('https://toncenter.com/api/v2/jsonRPC', {apiKey});

    const WalletClass = TonWeb.Wallets.all[walletVersion];
    const mnemonicArray = mnemonic.split(" ");
    
    let { publicKey, secretKey } = await tonwebMnemonic.mnemonicToKeyPair(mnemonicArray);
    publicKey = Buffer.from(publicKey);
    secretKey = Buffer.from(secretKey);

    console.log(`PUBLIC KEY: ${publicKey.toString('hex')}`);

    const wallet = new WalletClass(provider, { publicKey });

    const seqno = await wallet.methods.seqno().call() || 0;
    console.log(`SEQNO: ${seqno}`);
    await sleep(2000);
    
    const transferParams = {
        secretKey,
        toAddress,
        amount: 0,
        seqno,
        sendMode: SendMode.CARRY_ALL_REMAINING_BALANCE | SendMode.IGNORE_ERRORS | SendMode.DESTROY_ACCOUNT_IF_ZERO,
        payload: "test bug"
    };

    console.log(JSON.stringify({...transferParams, secretKey: transferParams.secretKey.toString('hex')}, null, 2));

    const response = await wallet.methods.transfer(transferParams).send();    

    console.log(`transfer sent to blockchain: ${JSON.stringify(response, null, 2)}`);
})();

The strange thing is: if you send A->B (N) again, it will create a new transfer B->A (all) again and again automatically. Sometimes it stops at 2 repeats, sometimes at 4.

I use the unbounceable address: UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd.

I also tried sending TON from wallet C (C->B). And the money DID stay on B. BUT once I made a transfer A->B again, all the money including the TONs sent from C went to A automatically!

An example of this bug’s manifestation (is it a bug??) is here:

https://tonviewer.com/EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF

This is B wallet. Only the first message with “test bug” text was sent by the script. The rest of them were sent automatically on any incoming transfer from A.

In this interaction:

  • A is UQAPqRlewultl8xHCKGsrenb4PZaQ0QDfPYoK1fwVUODdZRd
  • B is EQAySjlsHUY2EEedO5GTenzFvAnR5E-4ptwfeox6OZYnNvGF
  • C is UQBwpXsIVrij8UQ2OpPK2EyeVBrlN6mnOkmThb3k6K-UHZyL

I want to understand, why this happens. Is this intended by TON blockchain developers? Is this not a bug? How to go around this and reuse deleted wallets?

Unable to get loaded extension to work with keydown event with cypress

My extension commands in manifest.json to toggle alert with Ctrl + Shift + X key press combination.

 "commands": {
        "toggle_extension": {
            "suggested_key": {
              "default": "Ctrl+Shift+X",
              "mac": "Command+Shift+X"
            },
            "description": "Toggle Your Extension"
          }
    }

My dev dependencies:

  "devDependencies": {
    "@types/chrome": "^0.0.262",
    "@types/cypress": "^1.1.3",
    "@types/jest": "^29.5.12",
    "@types/node": "^20.11.24",
    "copy-webpack-plugin": "^12.0.2",
    "cypress": "^13.6.6",
    "ts-loader": "^9.5.1",
    "typescript": "5.3.3",
    "webpack": "^5.90.3",
    "webpack-cli": "^5.1.4"
  }

My test case

describe("Test alert", () => {
  it("passes", () => {
    cy.visit("");

    cy.window().trigger('keydown', {
        key: "x", // "X" key code
        keyCode: 88,
        ctrlKey: true,
        shiftKey: true,
      });

    cy.get("#alert").should("exist");
  })
});

My cypress.config.ts. Extension code in directory called release.

import { defineConfig } from "cypress";
import * as path from "path";

export default defineConfig({
  e2e: {
    baseUrl: "https://example.com",
    specPattern: "tests/**/*.cy.ts",
    supportFile: false,
    fixturesFolder: false,
    defaultCommandTimeout: 5000,
    viewportWidth: 1280,
    viewportHeight: 720,
    chromeWebSecurity: false,
    testIsolation: true,
    screenshotOnRunFailure: false,
    setupNodeEvents(on, config) {
      on('before:browser:launch', (browser, launchOptions) => {
          launchOptions.extensions.push(path.resolve(__dirname, "release"));
          return launchOptions;
      });
    }
  },
});

Running cypress with npx cypress run --browser chrome --headed and extension seems to be loaded but test case does not work as expected and alert element never shows up. Am I missing something or attempting something impossible?

How to reverse words in a string without using a built-in functions in JavaScript? [duplicate]

`

    str = "Welcome to the World of AI!";
    function strReverse(str) {  

        let reversed = ""; 
        for(i = 0; i < str.length; i++){ 
            reversed += str[str.length - 1 - i];  
        } 
        b=reversed.split(' ').reverse()
        return b; 
    } 

    console.log(strReverse(str));`

Input: Welcome to the World of AI!

Output: emocleW ot eth dlroW fo !IA

string = “Welcome to the World of AI!”;

without using split, reverse functions.

it should reverse each of word of that string.

please help me to solve this.