-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added the possibility to set an id to the iframe #25
Conversation
345189d
to
d47e298
Compare
Have you tried:
If you have, can you describe why it's not working for your use case? |
Sorry, I read the doc to quickly and didn't notice that the iframe element is returned. |
After some tests, using the iframe element returned by connectToChild is not usable. Indeed, when I try to get the iframe name from inside the iframe, it works on Firefox but not on Chrome. Below you will find the content of 2 files, just open parent.html in your browser. parent.html <!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/penpal/dist/penpal.min.js"></script>
<script type="text/javascript">
function createChilds() {
var foo = Penpal.connectToChild({
url: './child.html'
});
foo.iframe.id = 'foo';
var bar = document.createElement('iframe');
bar.id = 'bar';
bar.src = './child.html'
document.body.appendChild(bar);
}
window.addEventListener("load", createChilds);
</script>
</head>
<body></body>
</html> child.html <!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/penpal/dist/penpal.min.js"></script>
<script type="text/javascript">
function displayName() {
var div = document.createElement('div');
div.textContent = window.name || "window name not set";
document.body.appendChild(div);
}
window.addEventListener("load", displayName);
</script>
</head>
<body></body>
</html> I have an almost done update of the PR, which adds a new method Penpal.createChildConnection. This methods take the same args as Penpal.connectToChild and return the iframe, the destroy method and a connect method. The promise is returned when calling the connect method. import Penpal from 'penpal';
const connection = Penpal.createChildConnection({
// URL of page to load into iframe.
url: 'http://example.com/iframe.html',
// Container to which the iframe should be appended.
appendTo: document.getElementById('iframeContainer'),
// Methods parent is exposing to child
methods: {
add(num1, num2) {
return num1 + num2;
}
}
});
connection.connect().then(child => {
child.multiply(2, 6).then(total => console.log(total));
child.divide(12, 4).then(total => console.log(total));
}); Please note that the current PR by itself is useless as it allows only to set the iframe id and not the iframe name (the browser I'm targeting, an old webkit based one, derives the iframe name from the id if the name is not set. It looks like this is not working like that in more recent browsers). |
Thanks @ylesaout. I want to avoid opening up a new method. Let me do some research on the id/name stuff and get back to you. |
Another solution would be to add the possibility to pass an iframe element in the connectToChild method. Thus you would be able to call this method with an url, in which case Penpal will create the iframe element and append it to the DOM, or an iframe, in which case Penpal will only append the iframe to the DOM. By the way, getting a pointer to the iframe element only after it has been added to the DOM causes some troubles. Not only for my case with id/name but also for sandbox attribute which I believe is more important to take into account (see this PR #10). parent.html <!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/penpal/dist/penpal.min.js"></script>
<script type="text/javascript">
function shouldNotWork() {
var div = document.createElement('div');
div.textContent = "I shouldn't have been displayed";
document.body.appendChild(div);
}
function createChild() {
var connection = Penpal.connectToChild({
url: './child.html'
});
connection.iframe.sandbox = "allow-scripts";
}
window.addEventListener("load", createChild);
</script>
</head>
<body></body>
</html> child.html <!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
parent.shouldNotWork();
</script>
</head>
<body></body>
</html> |
Good find. Yeah, the security issue is certainly something that needs to be addressed. I agree with your proposal. Specifically: Add an option named What I'm on the fence about is whether to make the If you're willing to help out, I would appreciate any contribution to make this happen. We'll need updates to the source, documentation, tests, and the TypeScript typings. I'm not very familiar with TypeScript so I've largely depended on the other contributors for related help. Thanks again for doing the detective work on this and the help you've provided thus far. |
d47e298
to
9b6faac
Compare
You're welcome and thanks for the feedback and quick responses. About the URL parameter I don't have any opinion on either it should be optional or mandatory. So I will follow yours for the implementation. In the case that the iframe is already happened to the DOM, should the connectToChild method throw directly an error or do you prefer that the error to be thrown through the returned promise ? Or any other idea on what should be the behavior in this case ? |
The approach I would probably take is if the iframe is already added to the DOM, just remove it from the DOM before adding event listeners, setting the URL, and adding it back to the DOM. Then, in the docs for the |
Yes it makes sense, but it depends on how you want your lib to behave. Do you prefer having a lib that throws errors early or that fails silently and leads to unexpected behavior ? For example, imagine I have added the iframe to the DOM (but not at document.body) and I call connectToChild without appendTo option. Should the lib remove and append the iframe to document.body or to the current iframe parent element ? If I have I provide a different appenTo element than the current iframe parent element, should the lib append the iframe to the appenTo element or the current parent iframe element ? Another case, if I call connectToChild with an iframe that has a different src than the url provided in the call. Shoudl the lib replace the src attribute or not ? As I'm the guy that will add your lib in our code base, it doesn't matter. I have read the doc (more or less ;)) and, now, I hope I know exactly what I'm doing. However, other people will have to maintain the code I produce and they, surely, won't read the doc. They will update the code and it will work. Until the day there will have a guy that will append the iframe to the DOM before calling penpal ! And still it will work ! And some months later, another guy need to fix the code triggered by the iframe load event and notice that the event is triggered twice (if the lib removes and appends the iframe). If it's a smart guy he will search why the load event is triggered twice, and will read the doc, ..., otherwise it will just ignore the first load event and fix the bug by running the code only on the second event. And so on ... (FYI I have to maintain production code that checks, when an iframe in inserted in the DOM, that the URL is different than "about:blank", -- of course, synchronously, it is not-- and call a recursive setTimeout...) Thus, in my POV, it would be better not to change the current API and to add another function which takes an iframe instead of an URL. And this new method must raise an error if the iframe is already inserted in the DOM. With this API, the lib doesn't have to make opinionated choices. |
From your last comment, it sounds like, at least as a consumer, you have a preference toward throwing an error. Let's go with throwing an error if the iframe is already added to the DOM or These would have been my answers to your specific questions if we didn't throw an error:
The appendTo element.
Replace the URL. |
Indeed, I have a preference toward throwing an error. It's just that, by experience, if some libs had been more strict on their usage, lot of the bugs I have to fix won't have even been possible (people, at least on the project I'm working on currently, have preferred to rely on workarounds instead of finding and fixing the root cause). BTW, as you agree on throwing error, that's good in my POV and there is no need for a new method. I'll push an updated PR in the comming days. Note: As you may have noticed, english is not my native language. Reading the thread I may appear a little bit rude, but that's not my intention, I don't master all the nicety of english. Sorry for that! |
Hey, no problem! Your English is fine. I appreciate you being willing to help out and express your opinion. Let me know if you have questions or need help along the way. Thank you for the kind words about Penpal as well. We use it on some of our projects at work and it's worked out well for us. |
9b6faac
to
b7c036f
Compare
Hi, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's looking good! Thanks! I left a few comments.
@@ -55,6 +55,7 @@ export interface IConnectionOptions { | |||
export interface IChildConnectionOptions extends IConnectionOptions { | |||
url: string; | |||
appendTo?: HTMLElement; | |||
iframe?: HTMLIFrameElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like ERR_IFRAME_ALREADY_ATTACHED_TO_DOM
needs to be added to this file as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, it's done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it needs to be added at the bottom of the file like the other error constants as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, I have done the job to quickly (and as you, I'm not really familiar with TypeScript).
So I added it also to the export interface PenpalStatic
and as export const ERR_IFRAME_ALREADY_ATTACHED_TO_DOM
, like the other constants.
test/index.js
Outdated
add: (num1, num2) => { | ||
return num1 + num2; | ||
} | ||
it('throws ERR_IFRAME_ALREADY_ATTACHED_TO_DOM error of the iframe is already attached to DOM', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: should be "if the iframe"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
test/index.js
Outdated
url: `${CHILD_SERVER}/child.html`, | ||
appendTo: container | ||
|
||
it('creates an iframe and add it to a specific element', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both this test and the one before it should say "adds it to" instead of "add it to". That's my fault though. Don't feel like you have to fix it, but if you do, that'd be great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed as well
2860759
to
97e8179
Compare
I can help write the documentation if you'd like. Let me know. |
2bfdde9
to
eb615b6
Compare
As you know, help is always welcome ;). I just pushed a new commit with a first version of the documentation. So if you have any comments or improvements, I'll be be happy to update the documentation. |
eb615b6
to
1857c3b
Compare
Excellent. Thank you so much for the contribution. For the security issue you found on Firefox 64 on Ubuntu, is there an issue reported somewhere for that? I'm considering adding a link to it in the security notice. |
You're welcome ! |
Thanks. Let me know if you hear back. |
Published in v3.1.0. |
For some reasons, I need to have an id on the created iframe. Thus this PR.