1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef nsImportModule_h
8 #define nsImportModule_h
9
10 #include "mozilla/Attributes.h"
11
12 #include "nsCOMPtr.h"
13 #include "mozilla/RefPtr.h"
14
15 namespace mozilla {
16 namespace loader {
17
18 nsresult ImportModule(const char* aURI, const char* aExportName,
19 const nsIID& aIID, void** aResult);
20
21 } // namespace loader
22 } // namespace mozilla
23
24 class MOZ_STACK_CLASS nsImportModule final : public nsCOMPtr_helper {
25 public:
nsImportModule(const char * aURI,const char * aExportName,nsresult * aErrorPtr)26 nsImportModule(const char* aURI, const char* aExportName, nsresult* aErrorPtr)
27 : mURI(aURI), mExportName(aExportName), mErrorPtr(aErrorPtr) {}
28
operator()29 virtual nsresult NS_FASTCALL operator()(const nsIID& aIID,
30 void** aResult) const override {
31 nsresult rv =
32 ::mozilla::loader::ImportModule(mURI, mExportName, aIID, aResult);
33 if (mErrorPtr) {
34 *mErrorPtr = rv;
35 }
36 return rv;
37 }
38
39 private:
40 const char* mURI;
41 const char* mExportName;
42 nsresult* mErrorPtr;
43 };
44
45 /**
46 * These helpers make it considerably easier for C++ code to import a JS module
47 * and wrap it in an appropriately-defined XPIDL interface for its exports.
48 * Typical usage is something like:
49 *
50 * Foo.jsm:
51 *
52 * var EXPORTED_SYMBOLS = ["foo"];
53 *
54 * function foo(bar) {
55 * return bar.toString();
56 * }
57 *
58 * mozIFoo.idl:
59 *
60 * interface mozIFoo : nsISupports {
61 * AString foo(double meh);
62 * }
63 *
64 * Thing.cpp:
65 *
66 * nsCOMPtr<mozIFoo> foo = do_ImportModule(
67 * "resource://meh/Foo.jsm");
68 *
69 * MOZ_TRY(foo->Foo(42));
70 *
71 * For JS modules which export all fields within a single named object, a second
72 * argument can be passed naming that object.
73 *
74 * Foo.jsm:
75 *
76 * var EXPORTED_SYMBOLS = ["Foo"];
77 *
78 * var Foo = {
79 * function foo(bar) {
80 * return bar.toString();
81 * }
82 * };
83 *
84 * Thing.cpp:
85 *
86 * nsCOMPtr<mozIFoo> foo = do_ImportModule(
87 * "resource:://meh/Foo.jsm", "Foo");
88 */
89
90 template <size_t N>
do_ImportModule(const char (& aURI)[N])91 inline nsImportModule do_ImportModule(const char (&aURI)[N]) {
92 return {aURI, nullptr, nullptr};
93 }
94
95 template <size_t N>
do_ImportModule(const char (& aURI)[N],nsresult * aRv)96 inline nsImportModule do_ImportModule(const char (&aURI)[N], nsresult* aRv) {
97 return {aURI, nullptr, aRv};
98 }
99
100 template <size_t N, size_t N2>
do_ImportModule(const char (& aURI)[N],const char (& aExportName)[N2])101 inline nsImportModule do_ImportModule(const char (&aURI)[N],
102 const char (&aExportName)[N2]) {
103 return {aURI, aExportName, nullptr};
104 }
105
106 template <size_t N, size_t N2>
do_ImportModule(const char (& aURI)[N],const char (& aExportName)[N2],nsresult * aRv)107 inline nsImportModule do_ImportModule(const char (&aURI)[N],
108 const char (&aExportName)[N2],
109 nsresult* aRv) {
110 return {aURI, aExportName, aRv};
111 }
112
113 #endif // defined nsImportModule_h
114