Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
128463d
SK-2675 add origin check
skyflow-bharti Mar 30, 2026
bc77c0c
SK-2682 add target in bus events
skyflow-bharti Apr 1, 2026
92d4284
[AUTOMATED] Release - 2.7.4-dev.bc77c0c
skyflow-bharti Apr 1, 2026
73a206e
SK-2682 add target in bus events
skyflow-bharti Apr 1, 2026
d02eaf4
[AUTOMATED] Release - 2.7.4-dev.73a206e
skyflow-bharti Apr 1, 2026
689c150
SK-2682 fix the unit tests
skyflow-bharti Apr 1, 2026
ac3770f
[AUTOMATED] Release - 2.7.4-dev.689c150
skyflow-bharti Apr 1, 2026
b36fc55
SK-2682 fix the unit tests
skyflow-bharti Apr 1, 2026
5819c17
[AUTOMATED] Release - 2.7.4-dev.b36fc55
skyflow-bharti Apr 1, 2026
81aa0e9
SK-2682 fix the unit tests
skyflow-bharti Apr 1, 2026
efca6bf
[AUTOMATED] Release - 2.7.4-dev.81aa0e9
skyflow-bharti Apr 1, 2026
7a9dd9e
SK-2682 fix the origin check
skyflow-bharti Apr 17, 2026
9450798
[AUTOMATED] Release - 2.7.4-dev.7a9dd9e
skyflow-bharti Apr 17, 2026
d14e28a
Merge branch 'main' into release/26.3.30
skyflow-bharti May 5, 2026
5dbd12f
[AUTOMATED] Release - 2.7.5-dev.d14e28a
skyflow-bharti May 5, 2026
c85094c
SK-2682 fix targets
skyflow-bharti May 5, 2026
11429aa
[AUTOMATED] Release - 2.7.5-dev.c85094c
skyflow-bharti May 5, 2026
a53311b
SK-2682 add tests
skyflow-bharti May 5, 2026
11931a9
[AUTOMATED] Release - 2.7.5-dev.a53311b
skyflow-bharti May 5, 2026
9707cc4
SK-2682 add tests
skyflow-bharti May 5, 2026
0f6cfdc
[AUTOMATED] Release - 2.7.5-dev.9707cc4
skyflow-bharti May 5, 2026
9db8f20
SK-2682 add other missing checks
skyflow-bharti May 5, 2026
1dc45db
SK-2682 fix unit tests
skyflow-bharti May 5, 2026
676725a
Merge branch 'main' into release/26.3.30
skyflow-bharti May 5, 2026
9acbd0b
[AUTOMATED] Release - 2.7.6-dev.676725a
skyflow-bharti May 5, 2026
a1c6340
SK-2682 fix unit tests
skyflow-bharti May 5, 2026
e52687b
SK-2682 add unit tests
skyflow-bharti May 5, 2026
b373662
[AUTOMATED] Release - 2.7.6-dev.e52687b
skyflow-bharti May 5, 2026
fd29718
SK-2682 add unit tests
skyflow-bharti May 5, 2026
11c6bcc
[AUTOMATED] Release - 2.7.6-dev.fd29718
skyflow-bharti May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "skyflow-js",
"preferGlobal": true,
"analyze": false,
"version": "2.7.6",
"version": "2.7.6-dev.fd29718",
"author": "Skyflow",
"description": "Skyflow JavaScript SDK",
"homepage": "https://github.com/skyflowapi/skyflow-js",
Expand Down
25 changes: 14 additions & 11 deletions src/core/external/collect/compose-collect-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import SKYFLOW_ERROR_CODE from '../../../utils/constants';
import { ELEMENT_EVENTS_TO_CLIENT, ELEMENT_EVENTS_TO_IFRAME, ElementType } from '../../constants';
import { printLog } from '../../../utils/logs-helper';
import logs from '../../../utils/logs';
import properties from '../../../properties';

class ComposableElement {
#elementName: string;
Expand Down Expand Up @@ -134,17 +135,19 @@ class ComposableElement {
}
});
window.addEventListener('message', (event) => {
if (event?.data?.type === `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${this.#elementName}`) {
if (event?.data?.data?.errorResponse || event?.data?.data?.error) {
printLog(`${event?.data?.data.errorResponse || event?.data?.data.error}`, MessageType.ERROR, this.#context.logLevel);
reject(event?.data?.data);
} else if (event?.data?.data.fileUploadResponse) {
printLog(logs.infoLogs.MULTI_UPLOAD_FILES_SUCCESS,
MessageType.LOG, this.#context.logLevel);
resolve(event?.data?.data);
} else {
printLog(`${event?.data?.data}`, MessageType.ERROR, this.#context.logLevel);
reject(event?.data?.data);
if (event?.origin === properties.IFRAME_SECURE_ORIGIN) {
if (event?.data?.type === `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${this.#elementName}`) {
if (event?.data?.data?.errorResponse || event?.data?.data?.error) {
printLog(`${event?.data?.data.errorResponse || event?.data?.data.error}`, MessageType.ERROR, this.#context.logLevel);
reject(event?.data?.data);
} else if (event?.data?.data.fileUploadResponse) {
printLog(logs.infoLogs.MULTI_UPLOAD_FILES_SUCCESS,
MessageType.LOG, this.#context.logLevel);
resolve(event?.data?.data);
} else {
printLog(`${event?.data?.data}`, MessageType.ERROR, this.#context.logLevel);
reject(event?.data?.data);
}
}
}
});
Expand Down
83 changes: 44 additions & 39 deletions src/core/external/reveal/composable-reveal-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,27 +338,30 @@ class ComposableRevealInternalElement extends SkyflowElement {
},
);
window?.addEventListener('message', (event) => {
if (event?.data && event?.data?.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE
if (event?.origin === properties.IFRAME_SECURE_ORIGIN) {
if (event?.data
&& event?.data?.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE
+ recordData.name) {
if (event?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) {
const revealData = event?.data?.data?.result;
if (revealData?.error || revealData?.errors) {
printLog(parameterizedString(
logs.errorLogs.FAILED_RENDER,
), MessageType.ERROR,
this.#context.logLevel);
if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) {
this.setAltText(altText, recordData);
}
reject(revealData?.error || revealData?.errors);
} else {
printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME),
MessageType.LOG,
if (event?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) {
const revealData = event?.data?.data?.result;
if (revealData?.error || revealData?.errors) {
printLog(parameterizedString(
logs.errorLogs.FAILED_RENDER,
), MessageType.ERROR,
this.#context.logLevel);
printLog(parameterizedString(logs.infoLogs.FILE_RENDERED,
CLASS_NAME, recordData.skyflowID),
MessageType.LOG, this.#context.logLevel);
resolve(revealData);
if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) {
this.setAltText(altText, recordData);
}
reject(revealData?.error || revealData?.errors);
} else {
printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME),
MessageType.LOG,
this.#context.logLevel);
printLog(parameterizedString(logs.infoLogs.FILE_RENDERED,
CLASS_NAME, recordData.skyflowID),
MessageType.LOG, this.#context.logLevel);
resolve(revealData);
}
}
}
}
Expand Down Expand Up @@ -408,29 +411,31 @@ class ComposableRevealInternalElement extends SkyflowElement {
},
);
window.addEventListener('message', (event1) => {
if (event1?.data
if (event1?.origin === properties.IFRAME_SECURE_ORIGIN) {
if (event1?.data
&& event1?.data?.type === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE
+ recordData.name) {
if (event1?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) {
const revealData = event1?.data?.data?.result;
if (revealData?.error || revealData?.errors) {
printLog(parameterizedString(
logs.errorLogs.FAILED_RENDER,
), MessageType.ERROR,
this.#context.logLevel);
if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) {
this.setAltText(altText, recordData);
}
reject(revealData?.error || revealData?.errors);
} else {
// eslint-disable-next-line max-len
printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME),
MessageType.LOG,
if (event1?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) {
const revealData = event1?.data?.data?.result;
if (revealData?.error || revealData?.errors) {
printLog(parameterizedString(
logs.errorLogs.FAILED_RENDER,
), MessageType.ERROR,
this.#context.logLevel);
printLog(parameterizedString(logs.infoLogs.FILE_RENDERED,
CLASS_NAME, recordData.skyflowID),
MessageType.LOG, this.#context.logLevel);
resolve(revealData);
if (Object.prototype.hasOwnProperty.call(recordData, 'altText')) {
this.setAltText(altText, recordData);
}
reject(revealData?.error || revealData?.errors);
} else {
// eslint-disable-next-line max-len
printLog(parameterizedString(logs.infoLogs.RENDER_SUBMIT_SUCCESS, CLASS_NAME),
MessageType.LOG,
this.#context.logLevel);
printLog(parameterizedString(logs.infoLogs.FILE_RENDERED,
CLASS_NAME, recordData.skyflowID),
MessageType.LOG, this.#context.logLevel);
resolve(revealData);
}
}
}
}
Expand Down
66 changes: 34 additions & 32 deletions src/core/internal/reveal/reveal-frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,41 +300,43 @@ class RevealFrame {
);
this.updateRevealElementOptions();
window.addEventListener('message', (event) => {
if (event?.data?.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) {
if (event?.data?.data?.iframeName === this.#name
if (event?.origin === this.#clientDomain) {
if (event?.data?.name === ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_REQUESTS + this.#name) {
if (event?.data?.data?.iframeName === this.#name
&& event?.data?.data?.type === REVEAL_TYPES.RENDER_FILE) {
this.renderFile(this.#record, event?.data?.clientConfig,
event?.data?.errorMessages)?.then((resolvedResult) => {
const result = formatForRenderClient(
resolvedResult as IRenderResponseType,
this.#record?.column,
);
window?.parent?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name,
data: {
type: REVEAL_TYPES.RENDER_FILE,
result,
},
}, this.#clientDomain);

window?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window?.name,
}, properties?.IFRAME_SECURE_ORIGIN);
})?.catch((error) => {
window?.parent?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name,
data: {
type: REVEAL_TYPES.RENDER_FILE,
result: {
errors: error,
this.renderFile(this.#record, event?.data?.clientConfig,
event?.data?.errorMessages)?.then((resolvedResult) => {
const result = formatForRenderClient(
resolvedResult as IRenderResponseType,
this.#record?.column,
);
window?.parent?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name,
data: {
type: REVEAL_TYPES.RENDER_FILE,
result,
},
},
}, this.#clientDomain);
}, this.#clientDomain);

window?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window?.name,
}, properties?.IFRAME_SECURE_ORIGIN);
})?.catch((error) => {
window?.parent?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.REVEAL_CALL_RESPONSE + this.#name,
data: {
type: REVEAL_TYPES.RENDER_FILE,
result: {
errors: error,
},
},
}, this.#clientDomain);

window?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window?.name,
}, properties?.IFRAME_SECURE_ORIGIN);
});
window?.postMessage({
type: ELEMENT_EVENTS_TO_IFRAME.HEIGHT_CALLBACK_COMPOSABLE + window?.name,
}, properties?.IFRAME_SECURE_ORIGIN);
});
}
}
}

Expand Down
43 changes: 40 additions & 3 deletions tests/core/external/collect/composable-element.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import EventEmitter from "../../../../src/event-emitter";
import { ContainerType } from "../../../../src/skyflow";
import { ElementState } from "../../../../src/utils/common";
import SKYFLOW_ERROR_CODE from "../../../../src/utils/constants";
import properties from "../../../../src/properties";

describe("test composable element", () => {
const emitter = jest.fn();
Expand Down Expand Up @@ -162,6 +163,7 @@ describe("test composable element", () => {
// Trigger upload then dispatch error event AFTER listener is attached.
const p = testElement4.uploadMultipleFiles();
window.dispatchEvent(new MessageEvent('message', {
origin: properties.IFRAME_SECURE_ORIGIN,
data: {
type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:testce4`,
data: { error: 'Error occurred' }
Expand All @@ -180,6 +182,7 @@ describe("test composable element", () => {
// Trigger upload then dispatch error event AFTER listener is attached.
const p = testElement4.uploadMultipleFiles();
window.dispatchEvent(new MessageEvent('message', {
origin: properties.IFRAME_SECURE_ORIGIN,
data: {
type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:testce4`,
data: { error: 'Error occurred' }
Expand All @@ -198,6 +201,7 @@ describe("test composable element", () => {
// Trigger upload then dispatch error event AFTER listener is attached.
const p = testElement4.uploadMultipleFiles();
window.dispatchEvent(new MessageEvent('message', {
origin: properties.IFRAME_SECURE_ORIGIN,
data: {
type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:testce4`,
data: 'error occurred'
Expand All @@ -216,7 +220,7 @@ describe("test composable element", () => {
const promise = multiEl.uploadMultipleFiles();
expect(messageHandler).toBeDefined();
// Simulate success
messageHandler({ data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
await expect(promise).resolves.toMatchObject({ fileUploadResponse: [{ filename: 'doc.pdf' }] });
addSpy.mockRestore();
});
Expand All @@ -228,7 +232,7 @@ describe("test composable element", () => {
let messageHandler: any;
const addSpy = jest.spyOn(window, 'addEventListener').mockImplementation((evt, handler) => { if (evt === 'message') messageHandler = handler; });
const promise = multiEl.uploadMultipleFiles();
messageHandler({ data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { errorResponse: 'Upload failed' } } });
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { errorResponse: 'Upload failed' } } });
await expect(promise).rejects.toMatchObject({ errorResponse: 'Upload failed' });
addSpy.mockRestore();
});
Expand All @@ -240,8 +244,41 @@ describe("test composable element", () => {
let messageHandler: any;
const addSpy = jest.spyOn(window, 'addEventListener').mockImplementation((evt, handler) => { if (evt === 'message') messageHandler = handler; });
const promise = multiEl.uploadMultipleFiles();
messageHandler({ data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { error: 'Validation error' } } });
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { error: 'Validation error' } } });
await expect(promise).rejects.toMatchObject({ error: 'Validation error' });
addSpy.mockRestore();
});
it('uploadMultipleFiles ignores message from wrong origin', async () => {
const elementName = 'multiWrongOrigin';
const emitterStub: any = { _emit: jest.fn(), on: jest.fn() };
const multiEl = new ComposableElement(elementName, emitterStub, iframeName, { type: ElementType.MULTI_FILE_INPUT });
let messageHandler: any;
const addSpy = jest.spyOn(window, 'addEventListener').mockImplementation((evt, handler) => {
if (evt === 'message') messageHandler = handler;
});
const promise = multiEl.uploadMultipleFiles();
// Wrong origin — origin check is false, inner code skipped
messageHandler({ origin: 'https://attacker.com', data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
// Correct origin — now resolves
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
await expect(promise).resolves.toMatchObject({ fileUploadResponse: [{ filename: 'doc.pdf' }] });
addSpy.mockRestore();
});

it('uploadMultipleFiles ignores message with wrong event type', async () => {
const elementName = 'multiWrongType';
const emitterStub: any = { _emit: jest.fn(), on: jest.fn() };
const multiEl = new ComposableElement(elementName, emitterStub, iframeName, { type: ElementType.MULTI_FILE_INPUT });
let messageHandler: any;
const addSpy = jest.spyOn(window, 'addEventListener').mockImplementation((evt, handler) => {
if (evt === 'message') messageHandler = handler;
});
const promise = multiEl.uploadMultipleFiles();
// Correct origin but wrong type — type check is false, inner code skipped
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: 'WRONG_EVENT_TYPE', data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
// Correct type — now resolves
messageHandler({ origin: properties.IFRAME_SECURE_ORIGIN, data: { type: `${ELEMENT_EVENTS_TO_IFRAME.MULTIPLE_UPLOAD_FILES_RESPONSE}:${elementName}`, data: { fileUploadResponse: [{ filename: 'doc.pdf' }] } } });
await expect(promise).resolves.toMatchObject({ fileUploadResponse: [{ filename: 'doc.pdf' }] });
addSpy.mockRestore();
});
});
Loading
Loading