penpal 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/dist/penpal.js +773 -0
  4. package/dist/penpal.min.js +1 -0
  5. package/dist/penpal.min.js.map +1 -0
  6. package/es5/child/connectToParent.js +111 -0
  7. package/es5/child/handleSynAckMessageFactory.js +58 -0
  8. package/es5/connectCallReceiver.js +101 -0
  9. package/es5/connectCallSender.js +122 -0
  10. package/es5/createDestructor.js +29 -0
  11. package/es5/createLogger.js +19 -0
  12. package/es5/enums.js +47 -0
  13. package/es5/errorSerialization.js +34 -0
  14. package/es5/generateId.js +14 -0
  15. package/es5/index.js +63 -0
  16. package/es5/indexForBundle.js +21 -0
  17. package/es5/methodSerialization.js +94 -0
  18. package/es5/parent/connectToChild.js +107 -0
  19. package/es5/parent/getOriginFromSrc.js +53 -0
  20. package/es5/parent/handleAckMessageFactory.js +66 -0
  21. package/es5/parent/handleSynMessageFactory.js +29 -0
  22. package/es5/parent/monitorIframeRemoval.js +34 -0
  23. package/es5/parent/validateIframeHasSrcOrSrcDoc.js +18 -0
  24. package/es5/startConnectionTimeout.js +30 -0
  25. package/es5/types.js +1 -0
  26. package/lib/child/connectToParent.d.ts +36 -0
  27. package/lib/child/connectToParent.js +73 -0
  28. package/lib/child/handleSynAckMessageFactory.d.ts +7 -0
  29. package/lib/child/handleSynAckMessageFactory.js +41 -0
  30. package/lib/connectCallReceiver.d.ts +7 -0
  31. package/lib/connectCallReceiver.js +71 -0
  32. package/lib/connectCallSender.d.ts +14 -0
  33. package/lib/connectCallSender.js +93 -0
  34. package/lib/createDestructor.d.ts +13 -0
  35. package/lib/createDestructor.js +18 -0
  36. package/lib/createLogger.d.ts +2 -0
  37. package/lib/createLogger.js +10 -0
  38. package/lib/enums.d.ts +22 -0
  39. package/lib/enums.js +27 -0
  40. package/lib/errorSerialization.d.ts +14 -0
  41. package/lib/errorSerialization.js +17 -0
  42. package/lib/generateId.d.ts +5 -0
  43. package/lib/generateId.js +5 -0
  44. package/lib/index.d.ts +4 -0
  45. package/lib/index.js +3 -0
  46. package/lib/indexForBundle.d.ts +21 -0
  47. package/lib/indexForBundle.js +8 -0
  48. package/lib/methodSerialization.d.ts +27 -0
  49. package/lib/methodSerialization.js +67 -0
  50. package/lib/parent/connectToChild.d.ts +31 -0
  51. package/lib/parent/connectToChild.js +66 -0
  52. package/lib/parent/getOriginFromSrc.d.ts +5 -0
  53. package/lib/parent/getOriginFromSrc.js +42 -0
  54. package/lib/parent/handleAckMessageFactory.d.ts +7 -0
  55. package/lib/parent/handleAckMessageFactory.js +47 -0
  56. package/lib/parent/handleSynMessageFactory.d.ts +6 -0
  57. package/lib/parent/handleSynMessageFactory.js +18 -0
  58. package/lib/parent/monitorIframeRemoval.d.ts +12 -0
  59. package/lib/parent/monitorIframeRemoval.js +22 -0
  60. package/lib/parent/validateIframeHasSrcOrSrcDoc.d.ts +2 -0
  61. package/lib/parent/validateIframeHasSrcOrSrcDoc.js +8 -0
  62. package/lib/startConnectionTimeout.d.ts +6 -0
  63. package/lib/startConnectionTimeout.js +18 -0
  64. package/lib/types.d.ts +114 -0
  65. package/lib/types.js +0 -0
  66. package/package.json +90 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016, Aaron Hardy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ [![npm version](https://badge.fury.io/js/penpal.svg)](https://badge.fury.io/js/penpal)
2
+
3
+ ### Upgrading from version 5? See [version 6 release notes](https://github.com/Aaronius/penpal/releases/tag/v6.0.0) for details.
4
+
5
+ [See documentation for 5.x](https://github.com/Aaronius/penpal/tree/5.x)
6
+ [See documentation for 4.x](https://github.com/Aaronius/penpal/tree/4.x)
7
+ [See documentation for 3.x](https://github.com/Aaronius/penpal/tree/3.x)
8
+
9
+ # Penpal
10
+
11
+ Penpal is a promise-based library for securely communicating with iframes via postMessage. The parent window can call methods exposed by iframes, pass arguments, and receive a return value. Similarly, iframes can call methods exposed by the parent window, pass arguments, and receive a return value. Easy peasy.
12
+
13
+ This library has no dependencies.
14
+
15
+ ## Installation
16
+
17
+ ### Using npm
18
+
19
+ Preferably, you'll be able to use Penpal from npm with a bundler like [Webpack](https://webpack.github.io/), [Rollup](https://rollupjs.org), or [Parcel](https://parceljs.org/). If you use npm for client package management, you can install Penpal with:
20
+
21
+ `npm install penpal`
22
+
23
+ ### Using a CDN
24
+
25
+ If you don't want to use npm to manage client packages, Penpal also provides a UMD distribution in a `dist` folder which is hosted on a CDN:
26
+
27
+ `<script src="https://unpkg.com/penpal@^6/dist/penpal.min.js"></script>`
28
+
29
+ Penpal will then be installed on `window.Penpal`. `window.Penpal` will contain the following properties:
30
+
31
+ ```
32
+ Penpal.connectToChild
33
+ Penpal.connectToParent
34
+ Penpal.ErrorCode.ConnectionDestroyed
35
+ Penpal.ErrorCode.ConnectionTimeout
36
+ Penpal.ErrorCode.NoIframeSrc
37
+ ```
38
+
39
+ Usage is similar to if you were using a bundler, which is documented below, but instead of importing each module, you would access it on the `Penpal` global instead.
40
+
41
+ ## Usage
42
+
43
+ ### Parent Window
44
+
45
+ ```javascript
46
+ import { connectToChild } from 'penpal';
47
+
48
+ const iframe = document.createElement('iframe');
49
+ iframe.src = 'http://example.com/iframe.html';
50
+
51
+ // This conditional is not Penpal-specific. It's merely
52
+ // an example of how you can add an iframe to the document.
53
+ if (
54
+ document.readyState === 'complete' ||
55
+ document.readyState === 'interactive'
56
+ ) {
57
+ document.body.appendChild(iframe);
58
+ } else {
59
+ document.addEventListener('DOMContentLoaded', () => {
60
+ document.body.appendChild(iframe);
61
+ });
62
+ }
63
+
64
+ // This is where the magic begins.
65
+ const connection = connectToChild({
66
+ // The iframe to which a connection should be made.
67
+ iframe,
68
+ // Methods the parent is exposing to the child.
69
+ methods: {
70
+ add(num1, num2) {
71
+ return num1 + num2;
72
+ },
73
+ },
74
+ });
75
+
76
+ connection.promise.then((child) => {
77
+ child.multiply(2, 6).then((total) => console.log(total));
78
+ child.divide(12, 4).then((total) => console.log(total));
79
+ });
80
+ ```
81
+
82
+ ### Child Iframe
83
+
84
+ ```javascript
85
+ import { connectToParent } from 'penpal';
86
+
87
+ const connection = connectToParent({
88
+ // Methods child is exposing to parent.
89
+ methods: {
90
+ multiply(num1, num2) {
91
+ return num1 * num2;
92
+ },
93
+ divide(num1, num2) {
94
+ // Return a promise if the value being
95
+ // returned requires asynchronous processing.
96
+ return new Promise((resolve) => {
97
+ setTimeout(() => {
98
+ resolve(num1 / num2);
99
+ }, 1000);
100
+ });
101
+ },
102
+ },
103
+ });
104
+
105
+ connection.promise.then((parent) => {
106
+ parent.add(3, 1).then((total) => console.log(total));
107
+ });
108
+ ```
109
+
110
+ ## API
111
+
112
+ ### `connectToChild(options: Object) => Object`
113
+
114
+ **For Penpal to operate correctly, you must ensure that `connectToChild` is called before the iframe calls `connectToParent`.** As shown in the example above, it is safe to set the `src` or `srcdoc` property of the iframe and append the iframe to the document before calling `connectToChild` as long as they are both done in the same [JavaScript event loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop). Alternatively, you can always append the iframe to the document _after_ calling `connectToChild` instead of _before_.
115
+
116
+ #### Options
117
+
118
+ `options.iframe: HTMLIFrameElement` (required)
119
+
120
+ The iframe element to which Penpal should connect. Unless you provide the `childOrigin` option, you will need to have set either the `src` or `srcdoc` property on the iframe prior to calling `connectToChild` so that Penpal can automatically derive the child origin. In addition to regular URLs, [data URIs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) and [file URIs](https://en.wikipedia.org/wiki/File_URI_scheme) are also supported.
121
+
122
+ `options.methods: Object` (optional)
123
+
124
+ An object containing methods which should be exposed for the child iframe to call. The keys of the object are the method names and the values are the functions. Nested objects with function values are recursively included. If a function requires asynchronous processing to determine its return value, make the function immediately return a promise and resolve the promise once the value has been determined.
125
+
126
+ `options.childOrigin: string` (optional)
127
+
128
+ In the vast majority of cases, Penpal can automatically determine the child origin based on the `src` or `srcdoc` property that you have set on the iframe. This will automatically restrict communication to that origin.
129
+
130
+ In some rare cases, particularly when using the `file://` protocol on various devices, browsers are inconsistent in how they report and handle origins. If you receive an error saying that the parent received a handshake from an unexpected origin, you may need to manually pass the child origin using this option.
131
+
132
+ In other [niche scenarios](https://github.com/Aaronius/penpal/issues/73), you may want the parent to be able to communicate with any child origin. In this case, you can set `childOrigin` to `*`. **This is discouraged.** To illustrate the risk, if a nefarious attacker manages to create a link within the child page that another user can click (for example, if you fail to inadequately escape HTML in a message board comment), and that link navigates the unsuspecting user's iframe to a nefarious URL, then the page at the nefarious URL could start communicating with your parent window.
133
+
134
+ Regardless of how you configure `childOrigin`, communication will always be restricted to only the iframe to which you are connecting.
135
+
136
+ `options.timeout: number` (optional)
137
+
138
+ The amount of time, in milliseconds, Penpal should wait for the child to respond before rejecting the connection promise. There is no timeout by default.
139
+
140
+ `options.debug: boolean` (optional)
141
+
142
+ Enables or disables debug logging. Debug logging is disabled by default.
143
+
144
+ #### Return value
145
+
146
+ The return value of `connectToChild` is a `connection` object with the following properties:
147
+
148
+ `connection.promise: Promise`
149
+
150
+ A promise which will be resolved once communication has been established. The promise will be resolved with an object containing the methods which the child has exposed. Note that these aren't actual memory references to the methods the child exposed, but instead proxy methods Penpal has created with the same names and signatures. When one of these methods is called, Penpal will immediately return a promise and then go to work sending a message to the child, calling the actual method within the child with the arguments you have passed, and then sending the return value back to the parent. The promise you received will then be resolved with the return value.
151
+
152
+ `connection.destroy: Function`
153
+
154
+ A method that, when called, will disconnect any messaging channels. You may call this even before a connection has been established.
155
+
156
+ ### `connectToParent([options: Object]) => Object`
157
+
158
+ #### Options
159
+
160
+ `options.parentOrigin: string | RegExp` (optional **but highly recommended!**)
161
+
162
+ The origin of the parent window which your iframe will be communicating with. If this is not provided, communication will not be restricted to any particular parent origin resulting in any webpage being able to load your webpage into an iframe and communicate with it.
163
+
164
+ `options.methods: Object` (optional)
165
+
166
+ An object containing methods which should be exposed for the parent window to call. The keys of the object are the method names and the values are the functions. Nested objects with function values are recursively included. If a function requires asynchronous processing to determine its return value, make the function immediately return a promise and resolve the promise once the value has been determined.
167
+
168
+ `options.timeout: number` (optional)
169
+
170
+ The amount of time, in milliseconds, Penpal should wait for the parent to respond before rejecting the connection promise. There is no timeout by default.
171
+
172
+ `options.debug: boolean` (optional)
173
+
174
+ Enables or disables debug logging. Debug logging is disabled by default.
175
+
176
+ #### Return value
177
+
178
+ The return value of `connectToParent` is a `connection` object with the following properties:
179
+
180
+ `connection.promise: Promise`
181
+
182
+ A promise which will be resolved once communication has been established. The promise will be resolved with an object containing the methods which the parent has exposed. Note that these aren't actual memory references to the methods the parent exposed, but instead proxy methods Penpal has created with the same names and signatures. When one of these methods is called, Penpal will immediately return a promise and then go to work sending a message to the parent, calling the actual method within the parent with the arguments you have passed, and then sending the return value back to the child. The promise you received will then be resolved with the return value.
183
+
184
+ `connection.destroy: Function`
185
+
186
+ A method that, when called, will disconnect any messaging channels. You may call this even before a connection has been established.
187
+
188
+ ## Reconnection
189
+
190
+ If the child iframe attempts to reconnect with the parent, the parent will accept the new connection. This could happen, for example, if a user refreshes the child iframe or navigates within the iframe to a different page that also uses Penpal. In this case, the `child` object the parent received when the initial connection was established will be updated with the new methods provided by the child iframe.
191
+
192
+ NOTE: Currently there is no API to notify consumers of a reconnection. If this is important for you, please provide feedback on [this issue](https://github.com/Aaronius/penpal/issues/58) with how you would like to see the API designed.
193
+
194
+ ## Errors
195
+
196
+ Penpal will throw (or reject promises with) errors in certain situations. Each error will have a `code` property which may be used for programmatic decisioning (e.g., do something if the error was due to a connection timing out) along with a `message` describing the problem. Errors may be thrown with the following codes:
197
+
198
+ `ConnectionDestroyed`
199
+
200
+ This error will be thrown when attempting to call a method on `child` or `parent` objects and the connection was previously destroyed.
201
+
202
+ `ConnectionTimeout`
203
+
204
+ The promise found at `connection.promise` will be rejected with this error after the `timeout` duration has elapsed and a connection has not been established.
205
+
206
+ `NoIframeSrc`
207
+
208
+ This error will be thrown when the iframe passed into `connectToChild` does not have `src` or `srcdoc` set.
209
+
210
+ For your convenience, these error codes can be imported as follows:
211
+
212
+ ```
213
+ import { ErrorCode } from 'penpal';
214
+ // ErrorCode.ConnectionDestroyed
215
+ // ErrorCode.ConnectionTimeout
216
+ // ErrorCode.NoIframeSrc
217
+ ```
218
+
219
+ ## Supported Browsers
220
+
221
+ Penpal is designed to run successfully on the most recent versions of Chrome, Firefox, Safari, and Edge. If you need to support Internet Explorer 11, feel free to use version 3.x of Penpal. See the [3.x README](https://github.com/Aaronius/penpal/tree/3.x) for documentation.
222
+
223
+ Penpal has also been reported to work within Ionic projects on iOS and Android devices.
224
+
225
+ ## Inspiration
226
+
227
+ This library is inspired by:
228
+
229
+ - [Postmate](https://github.com/dollarshaveclub/postmate)
230
+ - [JSChannel](https://github.com/mozilla/jschannel)
231
+
232
+ ## License
233
+
234
+ MIT