Replacing content of div without triggering scrollend

I might have backed myself into a corner with this one, but I am creating an image carousel in svelte.

I want the carousel to work with horizontal scroll, and I want the image in the center to be wrapped with a different tag than the others.

so I’ve created this

    <div class="aspect-square overflow-hidden w-[520px] place-self-center">
        <div
            id="image-container"
            class="relative flex overflow-x-scroll snap-x snap-mandatory"
            style="scrollbar-width: none;"
            on:scrollend={(e) => {
                console.log("no longer scrolling", e);
                activeImage.set(distinctImages[Math.floor(e.target.scrollLeft / 520)])
            }}
        >
            {#each distinctImages as image}
                {#if image === $activeImage}
                    <FocusedHero {image} />
                {:else}
                    <Hero {image} />
                {/if}
            {/each}
        </div>
    </div>

It is a bit hacky, and I have the problem with it triggering scrollend whenever the content is being updated (which it is on scrollend, causing an infinite loop).

So is there any smarter way of doing this that works, and that keeps the requirement of having the “centered” image be of a different component?

Integrating Frontend JavaScript Code with AES Encryption getting ValueError: Data must be padded to 16 byte boundary in CBC mode

I’m currently working implementing AES encryption in the backend using Python, but I’m encountering some issues in ensuring compatibility between frontend and backedn. I need help in integrating the frontend JavaScript code to work with it.

My backend Python code:

class Crypt():
    def pad(self, data):
        BLOCK_SIZE = 16
        length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
        return data + (chr(length)*length)

    def unpad(self, data):
        return data[:-(data[-1] if type(data[-1]) == int else ord(data[-1]))]

    def bytes_to_key(self, data, salt, output=48):
        assert len(salt) == 8, len(salt)
        data += salt
        key = sha256(data).digest()
        final_key = key
        while len(final_key) < output:
            key = sha256(key + data).digest()
            final_key += key
        return final_key[:output]

    def bytes_to_key_md5(self, data, salt, output=48):
        assert len(salt) == 8, len(salt)
        data += salt
        key = md5(data).digest()
        final_key = key
        while len(final_key) < output:
            key = md5(key + data).digest()
            final_key += key
        return final_key[:output]

    def encrypt(self, message):
        passphrase = "<secret passpharse value>".encode()
        salt = Random.new().read(8)
        key_iv = self.bytes_to_key_md5(passphrase, salt, 32+16)
        key = key_iv[:32]
        iv = key_iv[32:]
        aes = AES.new(key, AES.MODE_CBC, iv)
        return base64.b64encode(b"Salted__" + salt + aes.encrypt(self.pad(message).encode()))

    def decrypt(self, encrypted):
        passphrase ="<secret passpharse value>".encode()
        encrypted = base64.b64decode(encrypted)
        assert encrypted[0:8] == b"Salted__"
        salt = encrypted[8:16]
        key_iv = self.bytes_to_key_md5(passphrase, salt, 32+16)
        key = key_iv[:32]
        iv = key_iv[32:]
        aes = AES.new(key, AES.MODE_CBC, iv)
        return self.unpad(aes.decrypt(encrypted[16:])).decode().strip('"')
    
    def base64_decoding(self, encoded):
        base64decode = base64.b64decode(encoded)
        return base64decode.decode()
    
crypt = Crypt()

test = "secret message to be send over network"

encrypted_message = crypt.encrypt(test)
print("Encryp msg:", encrypted_message)
decrypted_message = crypt.decrypt(encrypted_message)
print("Decryp:", decrypted_message)

here’s what I’ve tried so far on the frontend with React and CryptoJS:

    import React from "react";
import CryptoJS from 'crypto-js';

const DecryptEncrypt = () => {
    function bytesToKey(passphrase, salt, output = 48) {
        if (salt.length !== 8) {
            throw new Error('Salt must be 8 characters long.');
        }

        let data = CryptoJS.enc.Latin1.parse(passphrase + salt);
        let key = CryptoJS.SHA256(data).toString(CryptoJS.enc.Latin1);
        let finalKey = key;

        while (finalKey.length < output) {
            data = CryptoJS.enc.Latin1.parse(key + passphrase + salt);
            key = CryptoJS.SHA256(data).toString(CryptoJS.enc.Latin1);
            finalKey += key;
        }

        return finalKey.slice(0, output);
    }

    const decryptData = (encryptedData, key) => {
        const decodedEncryptedData = atob(encryptedData);
        const salt = CryptoJS.enc.Hex.parse(decodedEncryptedData.substring(8, 16));
        const ciphertext = CryptoJS.enc.Hex.parse(decodedEncryptedData.substring(16));
        const keyIv = bytesToKey(key, salt.toString(), 32 + 16);
        const keyBytes = CryptoJS.enc.Hex.parse(keyIv.substring(0, 32));
        const iv = CryptoJS.enc.Hex.parse(keyIv.substring(32));

        const decrypted = CryptoJS.AES.decrypt(
            { ciphertext: ciphertext },
            keyBytes,
            { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
        );

        
        return decrypted.toString(CryptoJS.enc.Utf8);
    };

    const encryptData = (data, key) => {
        const salt = CryptoJS.lib.WordArray.random(8); // Generate random salt
        const keyIv = bytesToKey(key, salt.toString(), 32 + 16);
        const keyBytes = CryptoJS.enc.Hex.parse(keyIv.substring(0, 32));
        const iv = CryptoJS.enc.Hex.parse(keyIv.substring(32));

        const encrypted = CryptoJS.AES.encrypt(data, keyBytes, {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        });

        const ciphertext = encrypted.ciphertext.toString(CryptoJS.enc.Hex);
        const saltedCiphertext = "Salted__" + salt.toString(CryptoJS.enc.Hex) + ciphertext;

        return btoa(saltedCiphertext);
    };

    const dataToEncrypt = 'Data to be sent over network';
    const encryptionKey = "<secret passpharse value>";

    const encryptedData = encryptData(dataToEncrypt, encryptionKey);
    console.log("Encrypted data:", encryptedData);

    const decryptedData = decryptData(encryptedData, encryptionKey);
    console.log("Decrypted data:", decryptedData);

    return (<>
        Check
    </>);
}

export default DecryptEncrypt;

I’m encountering some issues in ensuring compatibility between frontend and backedn. Specifically, I’m struggling with properly deriving the key and IV, and encrypting/decrypting the data in a way that matches the backend implementation. Getting error as below when i try to send encrypted text to backend where it throws following error while decrypting,

packagesCryptoCipher_mode_cbc.py", line 246, in decrypt
    raise ValueError("Data must be padded to %d byte boundary in CBC mode" % self.block_size)
ValueError: Data must be padded to 16 byte boundary in CBC mode

I m bit new to implementating AES in a fullstack app, so learning and trying but still stuck with this issue. Could someone who has encountered similar issue or implemented encryption/decryption in JavaScript offer some guidance or suggestions on how to modify my frontend code to achieve compatibility with the backend? Any insights, corrections, or alternative approaches would be very helpful.

currentUser data doesn’t update after changes to it when opening/closing a modal

i have a user profile modal in my next app where its data and the user can change it by typing in inputs. The problem is that old data doesn’t overwrites in modal when i open it or close but in my db it changes. I can get new data only after page refresh.

How i render it:

  <>
    {children}
    <LogOut />
    <Profile />
  </>

Modal:

export const Profile = () => {
  const searchParams = useSearchParams();
  const pathname = usePathname();
  const profileModal = searchParams.get("profileModal");

  const { currentUser } = useGetCurrentUser(); // get data from a custom hook

  return (
   ...
  );
};

JavaScript Selenium script: How to start my desktop electron app maximized or minimized?

Hello testing comunity i would like to ask if some one achieved to start there electron app maximized or minimized because i have tried everything by adding arguments for starting maximize when building the app and by using selenium driver.menage().window().maximize(). Is there any other solution?

The expectation was to maximize or minimize the desktop electron app.

How to import map-obj?

I’m trying to import this lib and I get the following error:

/Users/alexs/Documents/projects/xml-controller-test/dist/app.controller.js:20
const map_obj_1 = require("map-obj");
                  ^
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/alexs/Documents/projects/xml-controller-test/node_modules/map-obj/index.js from /Users/alexs/Documents/projects/xml-controller-test/dist/app.controller.js not supported.
Instead change the require of index.js in /Users/alexs/Documents/projects/xml-controller-test/dist/app.controller.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (/Users/alexs/Documents/projects/xml-controller-test/dist/app.controller.js:20:19)

I wouldn’t like to make any significant changes in my package.json that would the project. Though, I tried adding “type”: “module” to package.json, it didn’t help.

ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/Users/alexs/Documents/projects/xml-controller-test/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

The way I do it:

import mapObject, { mapObjectSkip } from 'map-obj';

I have a basic nestjs package.json and tsconfig.json files.
Is there any way to import this library in a TS project?

Cannot read properties of undefined (reading ‘3’) when trying to use (click) events in Angular

I’m trying to make an Angular site that can search for data based on a number of input fields. When I run the site locally using ng serve it works fine, but when I compile it with ng build and host the resulting files using a Docker container, it throws the error Cannot read properties of undefined (reading '3') in the console and fails to properly load the site.

Commenting out the two buttons at the bottom of the HTML template seems to make the error go away, and the page loads properly (apart from lacking buttons) so I’m thinking the problem might be something to do with the (click) event binding. Any idea how I can fix this?

The typescript file, search.component.ts:

import { Component } from '@angular/core';
import { SearchEntry } from '../student.service';
import { StudentService } from '../student.service';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrl: './search.component.css'
})
export class SearchComponent {
  constructor(private studentService: StudentService) {}
  searchParams: SearchEntry = {
    lifetimeID: '', uni: '', pid: '', lastName: '', firstName: '', gradYear: '',
    status: '', entryTerm: '', termNumber: '', program: '', cluster: ''
  };
  searchResults: SearchEntry[] = [];

  searchStudents(params: SearchEntry): void {
    const resultObs = this.studentService.searchStudents(params);
    resultObs.subscribe(results => this.searchResults = results);
  }

  clearFields(): void {
    this.searchParams = {
      lifetimeID: '', uni: '', pid: '', lastName: '', firstName: '', gradYear: '',
      status: '', entryTerm: '', termNumber: '', program: '', cluster: ''
    };
  }
}

The HTML template, search.component.html:

<div class="wrapper">
    <h4>Search for Entries</h4>
    <input [(ngModel)]="searchParams.lifetimeID" placeholder="Lifetime ID"><br>
    <input [(ngModel)]="searchParams.uni" placeholder="UNI"><br>
    <input [(ngModel)]="searchParams.pid" placeholder="PID"><br>
    <input [(ngModel)]="searchParams.lastName" placeholder="Last Name"><br>
    <input [(ngModel)]="searchParams.firstName" placeholder="First Name"><br>
    <input [(ngModel)]="searchParams.gradYear" placeholder="Grad Year"><br>
    <input [(ngModel)]="searchParams.status" placeholder="Status"><br>
    <input [(ngModel)]="searchParams.entryTerm" placeholder="Entry Term"><br>
    <input [(ngModel)]="searchParams.cluster" placeholder="Cluster"><br>
    <input [(ngModel)]="searchParams.program" placeholder="Program"><br>
    <input [(ngModel)]="searchParams.termNumber" placeholder="Term Number"><br>
    <button type="button" (click)="searchStudents(searchParams)">Search</button>
    <button type="button" (click)="clearFields()">Clear</button><br>
</div>

<app-student-list [results]="searchResults"></app-student-list>

The app-student-list component referenced on the last line of the HTML template appears to work fine on its own, so I didn’t include the code for it.

Pwa implementation in Yii2 PHP framework

I need to implement PWA for a project in Yii 2 framework in php. I have added the manifest.json file which is working as I checked in devtools. Also I added a service-worker file that registered successfull upon loading the browser. But the popup to install the app is not triggering in any device. I am stuck and need help.

sw.js

var staticCacheName = 'pwa-v' + new Date().getTime()

var filesToCache = [
        'css/bootstrap.css',
        'css/select2.min.css',
        'css/select2-bootstrap.css',
        'css/anno.css',
        'css/jquery.mThumbnailScroller.css',
        'css/jquery-ui.css',
        'css/bootstrap-theme.css',
        'css/fm.selectator.jquery.css',
        'css/lightgallery.min.css',
        'css/magnific-popup.css',
        'css/jquery.mCustomScrollbar.css',
        'css/bootstrap-datetimepicker.css',
        'css/croppie.css',
        'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/css/bootstrap-select.min.css',
        'css/developer.css',
        'css/empwin.css?v=2.37',
    'js/bootstrap.js?v=0.01',
        'js/fm.selectator.jquery.js?v=0.01',
        'js/lightgallery-all.min.js?v=0.01',
        'js/jquery.magnific-popup.min.js?v=0.01',
        'js/jquery.mThumbnailScroller.js?v=0.01',
        'js/moment.js?v=0.01',
        'js/bootstrap-datetimepicker.min.js?v=0.01',
        'js/highlight.min.js?v=0.01',
        'js/jquery-ui.js?v=0.01',
        'js/bootstrap-transition.js?v=0.01',
        'js/jquery.geocomplete.min.js?v=0.01',
        'js/croppie.js?v=0.01',
        'js/webcam.js?v=0.01',
        'js/anchorme.min.js?v=0.01',
        'js/anno.js?v=0.01',
        'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.11.2/js/bootstrap-select.min.js',
        'https://cdnjs.cloudflare.com/ajax/libs/jquery.lazyload/1.9.1/jquery.lazyload.min.js',
        'js/jquery.ui.core.min.js?v=0.01',
        'js/jquery.ui.timepicker.js?v=0.01',
        'js/jquery.pinBox.min.js?v=0.01',
        'js/propeller.min.js?v=0.01',
        'js/select2.full.js?v=0.01',
        'js/video.js?v=0.01',
        'js/jquery.mCustomScrollbar.concat.min.js?v=0.01',
        'js/custom.js?v=3.49',
        'js/custom1.js?v=0.02',
        'js/blur.js?v=0.01',
        'js/exif.js?v=0.02',
        'js/browser-deeplink.min.js',



]

// Cache on install
self.addEventListener("install", event => {
    this.skipWaiting();
    event.waitUntil(
        caches.open(staticCacheName)
            .then(cache => {
                return cache.addAll(filesToCache);
            })
    )
});

// Clear cache on activate
self.addEventListener('activate', event => {
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames
                    .filter(cacheName => (cacheName.startsWith("pwa-")))
                    .filter(cacheName => (cacheName !== staticCacheName))
                    .map(cacheName => caches.delete(cacheName))
            );
        })
    );
});

//Serve from Cache
self.addEventListener("fetch", event => {
    event.respondWith(
        caches.match(event.request)
            .then(response => {
                return response || fetch(event.request);
            })
            .catch(() => {
                return caches.match('offline');
            })
    )
});

manifest.json

{
    "theme_color": "#175795",
    "background_color": "#175795",
    "display": "standalone",
    "orientation": "portrait",
    "scope": "xxx",
    "start_url": "xxx",
    "name": "win",
    "icons": [
    {
      "src": "images/icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-96x96.png",
      "sizes": "96x96",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-144x144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-152x152.png",
      "sizes": "152x152",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-384x384.png",
      "sizes": "384x384",
      "type": "image/png"
    },
    {
      "src": "images/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
  
}

upload and process a potree file using threejs?

I’m currently exploring options for uploading and processing a Potree file using Three.js. I attempted to use the solution provided in the GitHub repository
https://github.com/pnext/three-loader?tab=readme-ov-file)
but unfortunately, it didn’t work out for me.

I was wondering if there is any alternative methods or resources that could help achieve this task? My objective is to enable the viewing of the Potree file directly within a web browser using Three.js. so i can process it……..

When creating an invoice on xero I get the error: TypeError: Converting circular structure to JSON

I am creating invoices on Xero but a couple of times (maybe 3 or 4 in about 1000 calls) i get the error: TypeError: Converting circular structure to JSON.

NOTE – the invoice is still being created

Here’s the code where im getting the error:

    const invoices = {
      invoices: [invoice],
    };

    let invoiceData: { body: Invoices } | undefined;
    try {
      invoiceData = await this.xero?.accountingApi.createInvoices(
        this.getTenantId(),
        invoices,
        true,
        4,
      );
    } catch (error: any) {
      const errors = error?.response?.body?.Elements?.[0]?.ValidationErrors;
      throw errors;
    }

    const invoiceNumber = invoiceData?.body?.invoices?.[0]?.invoiceNumber;

How to make the ball act more realisticly in my pong game?

i dont seem to make the ball react well..the ball only seems to go up when collides with the box…im programming with p5Play.js…https://github.com/simo8el8attar/MyPonggame.git

let box1;
let box2;
let ball;
let gameFloor1;
let gameFloor2;
let gameFloor3;
let gameFloor4;
function setup() {
    new Canvas(1270, 500);
  gameFloor1 =new Sprite(5, 245, 10, 500, 'static');
  gameFloor2 =new Sprite(1265, 245, 10, 500, 'static');
  gameFloor3 =new Sprite(0, 5, 2550, 10, 'static');
  gameFloor4 =new Sprite(0, 495, 2550, 10, 'static');
  
  box1 = new Sprite(25, 60, 20, 90, 'static');
  box2 = new Sprite(1240,160,20,90,'static');
  ball = new Sprite(800,300,30)
  ball.direction = 187;
  ball.speed = 6;
}

function draw() {
    background('black');
  box1.y = mouse.y
  box2.y = mouse.y
  
  if (box1.collides(ball)) {
        ball.direction = -400;
    ball.speed = 8;
    }
  if (box2.collides(ball)) {
        ball.direction = 187;
    ball.speed = 8;
    }
  if (gameFloor3.collides(ball)) {
    ball.speed = 8;
    }
  if (gameFloor4.collides(ball)) {
    ball.speed = 8;
    }
}

Problem sending file to server when in OneDrive

When the Excel file is synchronized via OneDrive and is open in the Excel application, when you try to select the file, the message “The file is in use” appears and this is correct. However, when I drag and drop the file, no message appears, but when sending the file to the server, the file is not sent.

Is there any way to check if a file is being used by another process? To be able to display the message yourself.

2d HTML5 game: How to dynamically add collision shapes to individual tiles?

I’m trying to write a multiplayer shooter game in HTML5 with Canvas. I have a function that loads 50 x 50 px map tiles like this in game.js:

const rotationKeys = {0: 0, 1: 90, 2: 180, 3: 270}

const tilemap = "0C0003 0W1003 0W0003 0W2003 0W3003 0W4003 0W0003".split(" "); // example

let tiles = {};

let collisionData = {}

function loadTiles() {
    for (const tileIndex in tilemap) {
        const rawTile = tilemap[tileIndex].substring(0, 3);
        const tileImg = new Image();
        tileImg.src = `sprites/maps/tiles/${rawTile}.png`;
        tiles[rawTile] = tileImg;
    }
}

function drawMap() {
    const tileSize = 50;
    gameSettings.mapWidth = 35;
    gameSettings.mapHeight = 24;

    const startX = Math.max(0, Math.floor(camera.x / (tileSize * scaleFactor)));
    const startY = Math.max(0, Math.floor(camera.y / (tileSize * scaleFactor)));

    const endX = Math.min(gameSettings.mapWidth, startX + Math.ceil(canvas.width / (tileSize * scaleFactor)) + 1);
    const endY = Math.min(gameSettings.mapHeight, startY + Math.ceil(canvas.height / (tileSize * scaleFactor)) + 1);
  
    for (let y = startY; y < endY; y++) {
      for (let x = startX; x < endX; x++) {
        const index = y * gameSettings.mapWidth + x;
        const tile = tilemap[index];
        const rotation = tile[3]; // Get rotation type for this tile
        const flip = tile[4]; // Get flip type for this tile
        const collision = parseInt(tile[5]); // Get collision type for this tile
  
        // Apply rotation transformation
        ctx.save(); // Save the current canvas state
        ctx.translate((x + 0.5) * tileSize * scaleFactor, (y + 0.5) * tileSize * scaleFactor); // Translate to the center of the tile
        ctx.rotate(rotationKeys[rotation] * Math.PI / 180); // Rotate by the specified angle (converted to radians)
  
        // Apply flip transformation
        var xScale = 1;
        var yScale = 1;
        if (flip == 1 || flip == 3) {
          xScale = -1;
        }
        if (flip == 2 || flip == 3) {
          yScale = -1;
        }
        ctx.scale(xScale, yScale);
  
        try {
            ctx.drawImage(tiles[tile.substring(0, 3)], -0.5 * tileSize * scaleFactor, -0.5 * tileSize * scaleFactor, tileSize * scaleFactor, tileSize * scaleFactor); // Draw the rotated image
        } catch (error) {
            console.error(`Failed to draw tile at (${x}, ${y}):`, error);
            console.log("Responsible tile:", tile);
        }
        ctx.restore(); // Restore the saved canvas state to undo the rotation transformation
      }
    }
}

There are 9 types of collision, where 0, 1 and 2 means the entire tile can be walked on. Where 3, 4 means that the entire tile is an obstacle (a wall for example). And the rest are basic rectangle shapes that are applied to the top of the 50×50 tile. The width of some shapes is 52, which exceed the tile size itself, resulting in extra edges. There is one shape that is a mixture of a rectangle and square.

Naturally, the collisions also need to go through the flip and rotation transformations, just like the tiles do.

My question is how can I do this? We should be able to detect that collision and not allow the player to go any further. He may continue to walk against the collision, it just shouldn’t let it walk on it.

I’ve tried something like this, but that didnt work as expected (misplacement and rotations/flips didnt work):

function generateCollisions(tileName, rotation, flip, collision) {
  // Check if collision data for this tile name already exists
  if (!(tileName in collisionData)) {

    // Determine collision shape based on collision type
    let collisionShape = null;

    switch (collision) {
      case 0:
      case 1:
      case 2:
        // The entire tile is walkable
        collisionShape = null; // No need to define a collision shape for walkable tiles
        break;
      case 3:
      case 4:
        // The entire tile is an obstacle
        collisionShape = { x: -1, y: -1, width: 52, height: 52 };
        break;
      case 5:
        collisionShape = { x: -1, y: 0, width: 52, height: 38 };
        break;
      case 6:
        collisionShape = { x: -1, y: 0, width: 52, height: 26 };
        break;
      case 7:
        collisionShape = { x: -1, y: 0, width: 52, height: 13 };
        break;
      case 8:
        collisionShape = { x: 0, y: 0, width: 26, height: 26 };
        break;
      case 9:
        collisionShape = { x: 24, y: 24, width: 26, height: 26 }; // this is a more complicated shape, should actually be a mix of rectangle of longer height and squre on top
        break;
    }

    if (collisionShape !== null && typeof collisionShape === 'object') {
      // Apply rotation and flip transformations to the collision shape
      const angleInRadians = rotationKeys[rotation] * Math.PI / 180;

      // Apply flip transformations
      if (flip === 1 || flip === 3) {
        collisionShape.x = 50 - collisionShape.x - collisionShape.width;
      }
      if (flip === 2 || flip === 3) {
        collisionShape.y = 50 - collisionShape.y - collisionShape.height;
      }

      // Apply rotation transformations
      const rotatedX = collisionShape.x * Math.cos(angleInRadians) - collisionShape.y * Math.sin(angleInRadians);
      const rotatedY = collisionShape.x * Math.sin(angleInRadians) + collisionShape.y * Math.cos(angleInRadians);

      // Update the collision shape with the transformed coordinates
      collisionShape.x = rotatedX;
      collisionShape.y = rotatedY;
    }

    collisionData[tileName] = collisionShape;
  }
}

NodeJS: Is it possible to pass modules to an isolate in isolated-vm?

I am trying to execute a script code inside isolated-vm‘s isolate. Script code needs some third party packages as dependencies like lodash, node-xlsx, etc.,. Is it possible to pass the dependent modules to an isolate?

Getting the following error while trying to pass module to an isolate:
TypeError: [object Module] could not be cloned.

Code:

import ivm from 'isolated-vm'
import _ from 'lodash-es'

(async function() {
        try{
                let code = `
                        async function setup() {
                                log('setup called!!');
                                log('config -> ', config);
                        }
                        setup();
                `;
                const isolate = new ivm.Isolate({ memoryLimit: 128 })
                const context = isolate.createContextSync()

                const jail = context.global
                jail.setSync('global', jail.derefInto());

                const config = {
                        id: 1234,
                        name: 'test'
                }
                jail.setSync('config', new ivm.ExternalCopy(config).copyInto());

                jail.setSync('libraries', new ivm.ExternalCopy(_).copyInto());

                jail.setSync('log', function(...args) {
                        console.log(...args);
                })

                const hostile = isolate.compileScriptSync(code)
                hostile.run(context).catch(err => console.error(err));

                        
        } catch(e) {
                console.log('err->', e)
        }
        
}) ()

Expected: Need to access libraries (lodash module) inside setup() function