зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to autoland
--HG-- rename : third_party/rust/nom/.cargo-checksum.json => third_party/rust/nom-3.2.1/.cargo-checksum.json rename : third_party/rust/nom/CHANGELOG.md => third_party/rust/nom-3.2.1/CHANGELOG.md rename : third_party/rust/nom/Cargo.toml => third_party/rust/nom-3.2.1/Cargo.toml rename : third_party/rust/nom/src/bits.rs => third_party/rust/nom-3.2.1/src/bits.rs rename : third_party/rust/nom/src/branch.rs => third_party/rust/nom-3.2.1/src/branch.rs rename : third_party/rust/nom/src/bytes.rs => third_party/rust/nom-3.2.1/src/bytes.rs rename : third_party/rust/nom/src/character.rs => third_party/rust/nom-3.2.1/src/character.rs rename : third_party/rust/nom/src/internal.rs => third_party/rust/nom-3.2.1/src/internal.rs rename : third_party/rust/nom/src/lib.rs => third_party/rust/nom-3.2.1/src/lib.rs rename : third_party/rust/nom/src/macros.rs => third_party/rust/nom-3.2.1/src/macros.rs rename : third_party/rust/nom/src/methods.rs => third_party/rust/nom-3.2.1/src/methods.rs rename : third_party/rust/nom/src/multi.rs => third_party/rust/nom-3.2.1/src/multi.rs rename : third_party/rust/nom/src/nom.rs => third_party/rust/nom-3.2.1/src/nom.rs rename : third_party/rust/nom/src/regexp.rs => third_party/rust/nom-3.2.1/src/regexp.rs rename : third_party/rust/nom/src/sequence.rs => third_party/rust/nom-3.2.1/src/sequence.rs rename : third_party/rust/nom/src/simple_errors.rs => third_party/rust/nom-3.2.1/src/simple_errors.rs rename : third_party/rust/nom/src/str.rs => third_party/rust/nom-3.2.1/src/str.rs rename : third_party/rust/nom/src/stream.rs => third_party/rust/nom-3.2.1/src/stream.rs rename : third_party/rust/nom/src/traits.rs => third_party/rust/nom-3.2.1/src/traits.rs rename : third_party/rust/nom/src/util.rs => third_party/rust/nom-3.2.1/src/util.rs rename : third_party/rust/nom/src/verbose_errors.rs => third_party/rust/nom-3.2.1/src/verbose_errors.rs rename : third_party/rust/nom/src/whitespace.rs => third_party/rust/nom-3.2.1/src/whitespace.rs rename : third_party/rust/nom/tests/arithmetic.rs => third_party/rust/nom-3.2.1/tests/arithmetic.rs rename : third_party/rust/nom/tests/arithmetic_ast.rs => third_party/rust/nom-3.2.1/tests/arithmetic_ast.rs rename : third_party/rust/nom/tests/blockbuf-arithmetic.rs => third_party/rust/nom-3.2.1/tests/blockbuf-arithmetic.rs rename : third_party/rust/nom/tests/cross_function_backtracking.rs => third_party/rust/nom-3.2.1/tests/cross_function_backtracking.rs rename : third_party/rust/nom/tests/float.rs => third_party/rust/nom-3.2.1/tests/float.rs rename : third_party/rust/nom/tests/ini.rs => third_party/rust/nom-3.2.1/tests/ini.rs rename : third_party/rust/nom/tests/ini_str.rs => third_party/rust/nom-3.2.1/tests/ini_str.rs rename : third_party/rust/nom/tests/issues.rs => third_party/rust/nom-3.2.1/tests/issues.rs rename : third_party/rust/nom/tests/json.rs => third_party/rust/nom-3.2.1/tests/json.rs rename : third_party/rust/nom/tests/mp4.rs => third_party/rust/nom-3.2.1/tests/mp4.rs rename : third_party/rust/nom/tests/multiline.rs => third_party/rust/nom-3.2.1/tests/multiline.rs rename : third_party/rust/nom/tests/named_args.rs => third_party/rust/nom-3.2.1/tests/named_args.rs rename : third_party/rust/nom/tests/omnom.rs => third_party/rust/nom-3.2.1/tests/omnom.rs rename : third_party/rust/nom/tests/overflow.rs => third_party/rust/nom-3.2.1/tests/overflow.rs rename : third_party/rust/nom/tests/reborrow_fold.rs => third_party/rust/nom-3.2.1/tests/reborrow_fold.rs rename : third_party/rust/nom/tests/test1.rs => third_party/rust/nom-3.2.1/tests/test1.rs extra : rebase_source : 6c5b45c092fd51bf1b3ce15960416fb59311d152
This commit is contained in:
Коммит
1ad50182a7
1
.hgtags
1
.hgtags
|
@ -152,3 +152,4 @@ ccfd7b716a91241ddbc084cb7116ec561e56d5d1 FIREFOX_BETA_61_BASE
|
|||
224715760a637bc37c14794839468a954f1f2695 FIREFOX_BETA_64_BASE
|
||||
224715760a637bc37c14794839468a954f1f2695 FIREFOX_BETA_64_BASE
|
||||
ad179a6fc14cbd41d10a018ac4a3822db119de3b FIREFOX_BETA_64_BASE
|
||||
c44fbdd5173548c9035256dda8fd3512f67118a8 FIREFOX_NIGHTLY_64_END
|
||||
|
|
2
CLOBBER
2
CLOBBER
|
@ -22,5 +22,5 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1488813 - Migrating Pocket off any bootstrap code
|
||||
|
||||
Merge day clobber
|
|
@ -160,7 +160,7 @@ dependencies = [
|
|||
name = "baldrdash"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-codegen 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cranelift-wasm 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -214,13 +214,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.39.0"
|
||||
version = "0.43.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -336,10 +336,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.2.3"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -359,7 +359,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "0.23.0"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1208,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "js"
|
||||
version = "0.1.4"
|
||||
dependencies = [
|
||||
"bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1232,7 +1232,7 @@ name = "jsrust_shared"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"baldrdash 0.1.0",
|
||||
"bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1679,6 +1679,14 @@ dependencies = [
|
|||
"memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nserror"
|
||||
version = "0.1.0"
|
||||
|
@ -2350,7 +2358,7 @@ dependencies = [
|
|||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayvec 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3124,7 +3132,7 @@ dependencies = [
|
|||
"checksum base64 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "85415d2594767338a74a30c1d370b2f3262ec1b4ed2d7bba5b3faf4de40467d9"
|
||||
"checksum binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88ceb0d16c4fd0e42876e298d7d3ce3780dd9ebdcbe4199816a32c77e08597ff"
|
||||
"checksum bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bda13183df33055cbb84b847becce220d392df502ebe7a4a78d7021771ed94d0"
|
||||
"checksum bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eac4ed5f2de9efc3c87cb722468fa49d0763e98f999d539bfc5e452c13d85c91"
|
||||
"checksum bindgen 0.43.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41df015ccbc22b038641bd84d0aeeff01e0a4c0714ed35ed0e9a3dd8ad8d732"
|
||||
"checksum binjs_meta 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "430239e4551e42b80fa5d92322ac80ea38c9dda56e5d5582e057e2288352b71a"
|
||||
"checksum bit-set 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1efcc46c18245a69c38fcc5cc650f16d3a59d034f3106e9ed63748f695730a"
|
||||
"checksum bit-vec 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4440d5cb623bb7390ae27fec0bb6c61111969860f8e3ae198bfa0663645e67cf"
|
||||
|
@ -3140,10 +3148,10 @@ dependencies = [
|
|||
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
|
||||
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
|
||||
"checksum cc 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "c37f0efaa4b9b001fa6f02d4b644dee4af97d3414df07c51e3e4f015f3a3e131"
|
||||
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
|
||||
"checksum cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fc0086be9ca82f7fc89fc873435531cb898b86e850005850de1f820e2db6e9b"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
|
||||
"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
|
||||
"checksum clang-sys 0.26.1 (registry+https://github.com/rust-lang/crates.io-index)" = "481e42017c1416b1c0856ece45658ecbb7c93d8a93455f7e5fa77f3b35455557"
|
||||
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
|
||||
"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb"
|
||||
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
|
||||
|
@ -3260,6 +3268,7 @@ dependencies = [
|
|||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
|
||||
"checksum nom 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9c349f68f25f596b9f44cf0e7c69752a5c633b0550c3ff849518bfba0233774a"
|
||||
"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"
|
||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
|
|
|
@ -439,11 +439,10 @@ NotificationController::ScheduleContentInsertion(nsIContent* aStartChildNode,
|
|||
node = node->GetNextSibling()) {
|
||||
MOZ_ASSERT(parent == node->GetFlattenedTreeParentNode());
|
||||
// Notification triggers for content insertion even if no content was
|
||||
// actually inserted, check if the given content has a frame to discard
|
||||
// actually inserted (like if the content is display: none). Try to catch
|
||||
// this case early.
|
||||
//
|
||||
// TODO(emilio): Should this handle display: contents?
|
||||
if (node->GetPrimaryFrame()) {
|
||||
if (node->GetPrimaryFrame() ||
|
||||
(node->IsElement() && node->AsElement()->IsDisplayContents())) {
|
||||
list.AppendElement(node);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,40 @@
|
|||
};
|
||||
}
|
||||
|
||||
// Test for bug 1500416.
|
||||
function displayContentsInsertion() {
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_REORDER, "c4"),
|
||||
];
|
||||
|
||||
this.invoke = function displayContentsInsertion_invoke() {
|
||||
document.body.offsetTop; // Flush layout.
|
||||
|
||||
let list = document.createElement("ul");
|
||||
list.style.display = "contents";
|
||||
list.appendChild(document.createElement("li"));
|
||||
list.firstChild.appendChild(document.createTextNode("Text"));
|
||||
getNode("c4").appendChild(list);
|
||||
};
|
||||
|
||||
this.finalCheck = function displayContentsInsertion_finalCheck() {
|
||||
var accTree =
|
||||
{ SECTION: [ // container
|
||||
{ LIST: [
|
||||
{ LISTITEM: [
|
||||
{ STATICTEXT: [] },
|
||||
{ TEXT_LEAF: [] },
|
||||
] },
|
||||
] },
|
||||
] };
|
||||
testAccessibleTree("c4", accTree);
|
||||
};
|
||||
|
||||
this.getID = function displayContentsInsertion_getID() {
|
||||
return "insert accessible display: contents element.";
|
||||
};
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////
|
||||
// Do tests
|
||||
// //////////////////////////////////////////////////////////////////////////
|
||||
|
@ -114,6 +148,7 @@
|
|||
gQueue.push(new prependAppend("c1"));
|
||||
gQueue.push(new removeRemove("c2"));
|
||||
gQueue.push(new insertInaccessibleAccessibleSiblings());
|
||||
gQueue.push(new displayContentsInsertion());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
@ -133,5 +168,6 @@
|
|||
<div id="c2"><span><input type="checkbox"><input></span><input type="button"></div>
|
||||
|
||||
<div id="c3"><input type="button" value="button"></div>
|
||||
<div id="c4"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -169,7 +169,7 @@ tags = fullscreen
|
|||
[browser_check_tooltips_in_navbar.js]
|
||||
[browser_editcontrols_update.js]
|
||||
subsuite = clipboard
|
||||
skip-if = verify && !debug && os == 'mac'
|
||||
skip-if = (verify && !debug && os == 'mac') || (os == 'mac') # Bug 1458046
|
||||
[browser_customization_context_menus.js]
|
||||
[browser_newtab_button_customizemode.js]
|
||||
[browser_open_from_popup.js]
|
||||
|
|
|
@ -38,6 +38,7 @@ skip-if = verify
|
|||
skip-if = os == "mac" #1421238
|
||||
[browser_private_search_perwindowpb.js]
|
||||
[browser_aboutSearchReset.js]
|
||||
disabled = bug 1488946 - Telemetry probe needs extension
|
||||
[browser_searchbar_openpopup.js]
|
||||
skip-if = os == "linux" # Linux has different focus behaviours.
|
||||
[browser_searchbar_keyboard_navigation.js]
|
||||
|
|
|
@ -1 +1 @@
|
|||
64.0a1
|
||||
65.0a1
|
||||
|
|
|
@ -1 +1 @@
|
|||
64.0a1
|
||||
65.0a1
|
||||
|
|
|
@ -40,10 +40,12 @@ run-if = crashreporter
|
|||
[browser_UsageTelemetry_private_and_restore.js]
|
||||
skip-if = verify && debug
|
||||
[browser_UsageTelemetry_urlbar.js]
|
||||
disabled = bug 1496764 - Telemetry probe needs extension
|
||||
support-files =
|
||||
usageTelemetrySearchSuggestions.sjs
|
||||
usageTelemetrySearchSuggestions.xml
|
||||
[browser_UsageTelemetry_searchbar.js]
|
||||
disabled = bug 1496764 - Telemetry probe needs extension
|
||||
support-files =
|
||||
usageTelemetrySearchSuggestions.sjs
|
||||
usageTelemetrySearchSuggestions.xml
|
||||
|
|
|
@ -10,4 +10,4 @@
|
|||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
64.0a1
|
||||
65.0a1
|
||||
|
|
|
@ -60,6 +60,7 @@ skip-if = true # Bug 1413765
|
|||
[browser_toolbox_computed_view.js]
|
||||
[browser_toolbox_rule_view.js]
|
||||
[browser_toolbox_rule_view_reload.js]
|
||||
skip-if = os == "linux" || os == "mac" # Bug 1498336
|
||||
[browser_toolbox_swap_browsers.js]
|
||||
[browser_toolbox_swap_inspector.js]
|
||||
[browser_touch_device.js]
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -477,6 +477,12 @@ private:
|
|||
nsresult
|
||||
MaybeRemoveOldDirectories();
|
||||
|
||||
template<typename Helper>
|
||||
nsresult
|
||||
UpgradeStorage(const int32_t aOldVersion,
|
||||
const int32_t aNewVersion,
|
||||
mozIStorageConnection* aConnection);
|
||||
|
||||
nsresult
|
||||
UpgradeStorageFrom0_0To1_0(mozIStorageConnection* aConnection);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ license = "MPL-2.0"
|
|||
|
||||
[build-dependencies]
|
||||
env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
|
||||
bindgen = {version = "0.39", default-features = false} # disable `logging` to reduce code size
|
||||
bindgen = {version = "0.43", default-features = false} # disable `logging` to reduce code size
|
||||
cmake = "0.1"
|
||||
glob = "0.2.11"
|
||||
|
||||
|
|
|
@ -299,16 +299,17 @@ function ModuleInstantiate()
|
|||
} catch (error) {
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
let m = stack[i];
|
||||
assert(m.status === MODULE_STATUS_INSTANTIATING,
|
||||
"Expected instantiating status during failed instantiation");
|
||||
HandleModuleInstantiationFailure(m);
|
||||
if (m.status === MODULE_STATUS_INSTANTIATING) {
|
||||
HandleModuleInstantiationFailure(m);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle OOM when appending to the stack or over-recursion errors.
|
||||
if (stack.length === 0)
|
||||
if (stack.length === 0 && module.status === MODULE_STATUS_INSTANTIATING) {
|
||||
HandleModuleInstantiationFailure(module);
|
||||
}
|
||||
|
||||
assert(module.status === MODULE_STATUS_UNINSTANTIATED,
|
||||
assert(module.status !== MODULE_STATUS_INSTANTIATING,
|
||||
"Expected uninstantiated status after failed instantiation");
|
||||
|
||||
throw error;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "mozilla/EnumSet.h"
|
||||
|
||||
#include "builtin/Promise.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/SharedContext.h"
|
||||
|
@ -1805,3 +1806,88 @@ js::GetOrCreateModuleMetaObject(JSContext* cx, HandleObject moduleArg)
|
|||
|
||||
return metaObject;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier)
|
||||
{
|
||||
JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
|
||||
if (!moduleResolveHook) {
|
||||
JS_ReportErrorASCII(cx, "Module resolve hook not set");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject result(cx, moduleResolveHook(cx, referencingPrivate, specifier));
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!result->is<ModuleObject>()) {
|
||||
JS_ReportErrorASCII(cx, "Module resolve hook did not return Module object");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::StartDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleValue specifierArg)
|
||||
{
|
||||
RootedObject promiseConstructor(cx, JS::GetPromiseConstructor(cx));
|
||||
if (!promiseConstructor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject promiseObject(cx, JS::NewPromiseObject(cx, nullptr));
|
||||
if (!promiseObject) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Handle<PromiseObject*> promise = promiseObject.as<PromiseObject>();
|
||||
|
||||
RootedString specifier(cx, ToString(cx, specifierArg));
|
||||
if (!specifier) {
|
||||
if (!RejectPromiseWithPendingError(cx, promise))
|
||||
return nullptr;
|
||||
return promise;
|
||||
}
|
||||
|
||||
JS::ModuleDynamicImportHook importHook = cx->runtime()->moduleDynamicImportHook;
|
||||
MOZ_ASSERT(importHook);
|
||||
if (!importHook(cx, referencingPrivate, specifier, promise)) {
|
||||
if (!RejectPromiseWithPendingError(cx, promise))
|
||||
return nullptr;
|
||||
return promise;
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
bool
|
||||
js::FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
|
||||
HandleObject promiseArg)
|
||||
{
|
||||
Handle<PromiseObject*> promise = promiseArg.as<PromiseObject>();
|
||||
|
||||
if (cx->isExceptionPending()) {
|
||||
return RejectPromiseWithPendingError(cx, promise);
|
||||
}
|
||||
|
||||
RootedObject result(cx, CallModuleResolveHook(cx, referencingPrivate, specifier));
|
||||
if (!result) {
|
||||
return RejectPromiseWithPendingError(cx, promise);
|
||||
}
|
||||
|
||||
RootedModuleObject module(cx, &result->as<ModuleObject>());
|
||||
if (module->status() != MODULE_STATUS_EVALUATED) {
|
||||
JS_ReportErrorASCII(cx, "Unevaluated or errored module returned by module resolve hook");
|
||||
return RejectPromiseWithPendingError(cx, promise);
|
||||
}
|
||||
|
||||
RootedObject ns(cx, ModuleObject::GetOrCreateModuleNamespace(cx, module));
|
||||
if (!ns) {
|
||||
return RejectPromiseWithPendingError(cx, promise);
|
||||
}
|
||||
|
||||
RootedValue value(cx, ObjectValue(*ns));
|
||||
return PromiseObject::resolve(cx, promise, value);
|
||||
}
|
||||
|
|
|
@ -419,6 +419,16 @@ class MOZ_STACK_CLASS ModuleBuilder
|
|||
JSObject*
|
||||
GetOrCreateModuleMetaObject(JSContext* cx, HandleObject module);
|
||||
|
||||
JSObject*
|
||||
CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier);
|
||||
|
||||
JSObject*
|
||||
StartDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleValue specifier);
|
||||
|
||||
bool
|
||||
FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
|
||||
HandleObject promise);
|
||||
|
||||
} // namespace js
|
||||
|
||||
template<>
|
||||
|
|
|
@ -3404,6 +3404,16 @@ OriginalPromiseThenBuiltin(JSContext* cx, HandleValue promiseVal, HandleValue on
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
js::RejectPromiseWithPendingError(JSContext* cx, Handle<PromiseObject*> promise)
|
||||
{
|
||||
// Not much we can do about uncatchable exceptions, just bail.
|
||||
RootedValue exn(cx);
|
||||
if (!GetAndClearException(cx, &exn))
|
||||
return false;
|
||||
return PromiseObject::reject(cx, promise, exn);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool PerformPromiseThenWithReaction(JSContext* cx,
|
||||
Handle<PromiseObject*> promise,
|
||||
Handle<PromiseReactionRecord*> reaction);
|
||||
|
|
|
@ -225,6 +225,8 @@ OriginalPromiseThen(JSContext* cx, HandleObject promiseObj,
|
|||
MOZ_MUST_USE JSObject*
|
||||
PromiseResolve(JSContext* cx, HandleObject constructor, HandleValue value);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
RejectPromiseWithPendingError(JSContext* cx, Handle<PromiseObject*> promise);
|
||||
|
||||
/**
|
||||
* Create the promise object which will be used as the return value of an async
|
||||
|
|
|
@ -523,16 +523,6 @@ ReportArgTypeError(JSContext* cx, const char* funName, const char* expectedType,
|
|||
expectedType, bytes.get());
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
RejectWithPendingError(JSContext* cx, Handle<PromiseObject*> promise) {
|
||||
// Not much we can do about uncatchable exceptions, just bail.
|
||||
RootedValue exn(cx);
|
||||
if (!GetAndClearException(cx, &exn)) {
|
||||
return false;
|
||||
}
|
||||
return PromiseObject::reject(cx, promise, exn);
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
ReturnPromiseRejectedWithPendingError(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
|
@ -1461,7 +1451,7 @@ ReadableStreamTee_Cancel(JSContext* cx, Handle<TeeState*> teeState,
|
|||
{
|
||||
AutoRealm ar(cx, promise);
|
||||
if (!cancelResult) {
|
||||
if (!RejectWithPendingError(cx, promise)) {
|
||||
if (!RejectPromiseWithPendingError(cx, promise)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -8878,8 +8878,14 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage::
|
|||
break;
|
||||
|
||||
case ParseNodeKind::CallImport:
|
||||
reportError(nullptr, JSMSG_NO_DYNAMIC_IMPORT);
|
||||
return false;
|
||||
if (!cx->runtime()->moduleDynamicImportHook) {
|
||||
reportError(nullptr, JSMSG_NO_DYNAMIC_IMPORT);
|
||||
return false;
|
||||
}
|
||||
if (!emitTree(pn->as<BinaryNode>().right()) || !emit1(JSOP_DYNAMIC_IMPORT)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ParseNodeKind::SetThis:
|
||||
if (!emitSetThis(&pn->as<BinaryNode>())) {
|
||||
|
|
|
@ -573,7 +573,7 @@ FOR_EACH_PARSENODE_SUBCLASS(DECLARE_AS)
|
|||
}
|
||||
|
||||
BinaryNodeType newCallImport(NullaryNodeType importHolder, Node singleArg) {
|
||||
return new_<BinaryNode>(ParseNodeKind::CallImport, JSOP_NOP, importHolder, singleArg);
|
||||
return new_<BinaryNode>(ParseNodeKind::CallImport, JSOP_DYNAMIC_IMPORT, importHolder, singleArg);
|
||||
}
|
||||
|
||||
UnaryNodeType newExprStatement(Node expr, uint32_t end) {
|
||||
|
|
|
@ -10913,7 +10913,7 @@ GeneralParser<ParseHandler, Unit>::importExpr(YieldHandling yieldHandling)
|
|||
|
||||
MUST_MATCH_TOKEN_MOD(TokenKind::RightParen, TokenStream::Operand, JSMSG_PAREN_AFTER_ARGS);
|
||||
|
||||
if (!abortIfSyntaxParser()) {
|
||||
if (!context->runtime()->moduleDynamicImportHook && !abortIfSyntaxParser()) {
|
||||
return null();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// |jit-test| module
|
||||
|
||||
let result = null;
|
||||
let error = null;
|
||||
let promise = import("nonexistent.js");
|
||||
promise.then((ns) => {
|
||||
result = ns;
|
||||
}).catch((e) => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
drainJobQueue();
|
||||
assertEq(result, null);
|
||||
assertEq(error instanceof Error, true);
|
|
@ -77,9 +77,3 @@ assertParseThrowsSyntaxError("x = import(");
|
|||
assertParseThrowsSyntaxError("x = import(1,");
|
||||
assertParseThrowsSyntaxError("x = import(1, 2");
|
||||
assertParseThrowsSyntaxError("x = import(1, 2)");
|
||||
|
||||
// import() is not implemented.
|
||||
assertThrowsInstanceOf(() => eval("import('foo')"),
|
||||
SyntaxError);
|
||||
assertThrowsInstanceOf(() => parseModule("import('foo')"),
|
||||
SyntaxError);
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Even with --ion-eager, this needs to be run twice before it executes the
|
||||
// ion-compiled version.
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let result = null;
|
||||
let error = null;
|
||||
let promise = import("../../modules/module1.js");
|
||||
promise.then((ns) => {
|
||||
result = ns;
|
||||
}).catch((e) => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
drainJobQueue();
|
||||
assertEq(error, null);
|
||||
assertEq(result.a, 1);
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
// |jit-test| error: SyntaxError
|
||||
|
||||
function lazyilyParsedFunction()
|
||||
{
|
||||
return import("/module1.js");
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// |jit-test| module
|
||||
|
||||
function testImport(path, name, value) {
|
||||
let result = null;
|
||||
let error = null;
|
||||
let promise = import(path);
|
||||
promise.then((ns) => {
|
||||
result = ns;
|
||||
}).catch((e) => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
drainJobQueue();
|
||||
assertEq(error, null);
|
||||
assertEq(result[name], value);
|
||||
}
|
||||
|
||||
// Resolved via module load path.
|
||||
testImport("module1.js", "a", 1);
|
||||
|
||||
// Relative path resolved relative to this script.
|
||||
testImport("../../modules/module1a.js", "a", 2);
|
||||
|
||||
// Import inside function.
|
||||
function f() {
|
||||
testImport("../../modules/module2.js", "b", 2);
|
||||
}
|
||||
f();
|
||||
|
||||
// Import inside direct eval.
|
||||
eval(`testImport("../../modules/module3.js", "c", 3)`);
|
||||
|
||||
// Import inside indirect eval.
|
||||
const indirect = eval;
|
||||
const defineTestFunc = testImport.toSource();
|
||||
indirect(defineTestFunc + `testImport("../../modules/module3.js");`);
|
||||
|
||||
// Import inside dynamic function.
|
||||
Function(defineTestFunc + `testImport("../../modules/module3.js");`)();
|
|
@ -0,0 +1,4 @@
|
|||
// |jit-test| skip-if: !('oomTest' in this)
|
||||
|
||||
oomTest(() => import("module1.js"));
|
||||
oomTest(() => import("cyclicImport1.js"));
|
|
@ -0,0 +1,45 @@
|
|||
function testImport(path, name, value) {
|
||||
let result = null;
|
||||
let error = null;
|
||||
let promise = import(path);
|
||||
promise.then((ns) => {
|
||||
result = ns;
|
||||
}).catch((e) => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
drainJobQueue();
|
||||
assertEq(error, null);
|
||||
assertEq(result[name], value);
|
||||
}
|
||||
|
||||
// Resolved via module load path.
|
||||
testImport("module1.js", "a", 1);
|
||||
|
||||
// Relative path resolved relative to this script.
|
||||
testImport("../../modules/module1a.js", "a", 2);
|
||||
|
||||
// Import inside function.
|
||||
function f() {
|
||||
testImport("../../modules/module2.js", "b", 2);
|
||||
}
|
||||
f();
|
||||
|
||||
// Import inside eval.
|
||||
eval(`testImport("../../modules/module3.js", "c", 3)`);
|
||||
|
||||
// Import inside indirect eval.
|
||||
const indirect = eval;
|
||||
const defineTestFunc = testImport.toSource();
|
||||
indirect(defineTestFunc + `testImport("../../modules/module3.js");`);
|
||||
|
||||
// Import inside dynamic function.
|
||||
Function(defineTestFunc + `testImport("../../modules/module3.js");`)();
|
||||
|
||||
// Import in eval in promise handler.
|
||||
let ran = false;
|
||||
Promise
|
||||
.resolve(`import("../../modules/module3.js").then(() => { ran = true; })`)
|
||||
.then(eval)
|
||||
drainJobQueue();
|
||||
assertEq(ran, true);
|
|
@ -0,0 +1,17 @@
|
|||
// |jit-test| module
|
||||
|
||||
import { a } from "javascript: export let a = 42;";
|
||||
assertEq(a, 42);
|
||||
|
||||
let result = null;
|
||||
let error = null;
|
||||
let promise = import("javascript: export let b = 100;");
|
||||
promise.then((ns) => {
|
||||
result = ns;
|
||||
}).catch((e) => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
drainJobQueue();
|
||||
assertEq(error, null);
|
||||
assertEq(result.b, 100);
|
|
@ -5451,3 +5451,28 @@ BaselineCompiler::emit_JSOP_IMPORTMETA()
|
|||
frame.push(R0);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue, HandleValue);
|
||||
static const VMFunction StartDynamicModuleImportInfo =
|
||||
FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
|
||||
"StartDynamicModuleImport");
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_DYNAMIC_IMPORT()
|
||||
{
|
||||
RootedValue referencingPrivate(cx, FindScriptOrModulePrivateForScript(script));
|
||||
|
||||
// Put specifier value in R0.
|
||||
frame.popRegsAndSync(1);
|
||||
|
||||
prepareVMCall();
|
||||
pushArg(R0);
|
||||
pushArg(referencingPrivate);
|
||||
if (!callVM(StartDynamicModuleImportInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
|
||||
frame.push(R0);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -245,7 +245,8 @@ namespace jit {
|
|||
_(JSOP_FUNWITHPROTO) \
|
||||
_(JSOP_CLASSCONSTRUCTOR) \
|
||||
_(JSOP_DERIVEDCONSTRUCTOR) \
|
||||
_(JSOP_IMPORTMETA)
|
||||
_(JSOP_IMPORTMETA) \
|
||||
_(JSOP_DYNAMIC_IMPORT)
|
||||
|
||||
class BaselineCompiler final
|
||||
{
|
||||
|
|
|
@ -3025,6 +3025,19 @@ CodeGenerator::visitModuleMetadata(LModuleMetadata* lir)
|
|||
callVM(GetOrCreateModuleMetaObjectInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSObject* (*StartDynamicModuleImportFn)(JSContext*, HandleValue, HandleValue);
|
||||
static const VMFunction StartDynamicModuleImportInfo =
|
||||
FunctionInfo<StartDynamicModuleImportFn>(js::StartDynamicModuleImport,
|
||||
"StartDynamicModuleImport");
|
||||
|
||||
void
|
||||
CodeGenerator::visitDynamicImport(LDynamicImport* lir)
|
||||
{
|
||||
pushArg(ToValue(lir, LDynamicImport::SpecifierIndex));
|
||||
pushArg(ToValue(lir, LDynamicImport::ReferencingPrivateIndex));
|
||||
callVM(StartDynamicModuleImportInfo, lir);
|
||||
}
|
||||
|
||||
typedef JSObject* (*LambdaFn)(JSContext*, HandleFunction, HandleObject);
|
||||
static const VMFunction LambdaInfo = FunctionInfo<LambdaFn>(js::Lambda, "Lambda");
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "jit/Lowering.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/Opcodes.h"
|
||||
#include "vm/RegExpStatics.h"
|
||||
#include "vm/TraceLogging.h"
|
||||
|
@ -2489,6 +2490,9 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
case JSOP_IMPORTMETA:
|
||||
return jsop_importmeta();
|
||||
|
||||
case JSOP_DYNAMIC_IMPORT:
|
||||
return jsop_dynamic_import();
|
||||
|
||||
case JSOP_LOOPENTRY:
|
||||
return jsop_loopentry();
|
||||
|
||||
|
@ -13828,6 +13832,20 @@ IonBuilder::jsop_importmeta()
|
|||
return resumeAfter(meta);
|
||||
}
|
||||
|
||||
AbortReasonOr<Ok>
|
||||
IonBuilder::jsop_dynamic_import()
|
||||
{
|
||||
Value referencingPrivate = FindScriptOrModulePrivateForScript(script());
|
||||
MConstant* ref = constant(referencingPrivate);
|
||||
|
||||
MDefinition* specifier = current->pop();
|
||||
|
||||
MDynamicImport* ins = MDynamicImport::New(alloc(), ref, specifier);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
return resumeAfter(ins);
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addConvertElementsToDoubles(MDefinition* elements)
|
||||
{
|
||||
|
|
|
@ -593,6 +593,7 @@ class IonBuilder
|
|||
AbortReasonOr<Ok> jsop_pushcallobj();
|
||||
AbortReasonOr<Ok> jsop_implicitthis(PropertyName* name);
|
||||
AbortReasonOr<Ok> jsop_importmeta();
|
||||
AbortReasonOr<Ok> jsop_dynamic_import();
|
||||
|
||||
/* Inlining. */
|
||||
|
||||
|
|
|
@ -2602,6 +2602,15 @@ LIRGenerator::visitModuleMetadata(MModuleMetadata* ins)
|
|||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitDynamicImport(MDynamicImport* ins)
|
||||
{
|
||||
LDynamicImport* lir = new(alloc()) LDynamicImport(useBoxAtStart(ins->referencingPrivate()),
|
||||
useBoxAtStart(ins->specifier()));
|
||||
defineReturn(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitLambda(MLambda* ins)
|
||||
{
|
||||
|
|
|
@ -7819,6 +7819,22 @@ class MModuleMetadata : public MNullaryInstruction
|
|||
}
|
||||
};
|
||||
|
||||
class MDynamicImport : public MBinaryInstruction,
|
||||
public BoxInputsPolicy::Data
|
||||
{
|
||||
explicit MDynamicImport(MDefinition* referencingPrivate, MDefinition* specifier)
|
||||
: MBinaryInstruction(classOpcode, referencingPrivate, specifier)
|
||||
{
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(DynamicImport)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, referencingPrivate))
|
||||
NAMED_OPERANDS((1, specifier))
|
||||
};
|
||||
|
||||
struct LambdaFunctionInfo
|
||||
{
|
||||
// The functions used in lambdas are the canonical original function in
|
||||
|
|
|
@ -4903,6 +4903,27 @@ class LModuleMetadata : public LCallInstructionHelper<1, 0, 0>
|
|||
{}
|
||||
};
|
||||
|
||||
class LDynamicImport : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(DynamicImport)
|
||||
|
||||
static const size_t ReferencingPrivateIndex = 0;
|
||||
static const size_t SpecifierIndex = BOX_PIECES;
|
||||
|
||||
explicit LDynamicImport(const LBoxAllocation& referencingPrivate,
|
||||
const LBoxAllocation& specifier)
|
||||
: LCallInstructionHelper(classOpcode)
|
||||
{
|
||||
setBoxOperand(ReferencingPrivateIndex, referencingPrivate);
|
||||
setBoxOperand(SpecifierIndex, specifier);
|
||||
}
|
||||
|
||||
const MDynamicImport* mir() const {
|
||||
return mir_->toDynamicImport();
|
||||
}
|
||||
};
|
||||
|
||||
class LLambdaForSingleton : public LCallInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -615,6 +615,7 @@ MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found f
|
|||
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
|
||||
MSG_DEF(JSMSG_BAD_MODULE_STATUS, 0, JSEXN_INTERNALERR, "module record has unexpected status")
|
||||
MSG_DEF(JSMSG_NO_DYNAMIC_IMPORT, 0, JSEXN_SYNTAXERR, "dynamic module import is not implemented")
|
||||
MSG_DEF(JSMSG_IMPORT_SCRIPT_NOT_FOUND, 0, JSEXN_TYPEERR, "can't find referencing script for dynamic module import")
|
||||
|
||||
// Promise
|
||||
MSG_DEF(JSMSG_CANNOT_RESOLVE_PROMISE_WITH_ITSELF, 0, JSEXN_TYPEERR, "A promise cannot be resolved with itself.")
|
||||
|
|
|
@ -4141,6 +4141,31 @@ JS::SetModuleMetadataHook(JSRuntime* rt, JS::ModuleMetadataHook func)
|
|||
rt->moduleMetadataHook = func;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::ModuleDynamicImportHook)
|
||||
JS::GetModuleDynamicImportHook(JSRuntime* rt)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
return rt->moduleDynamicImportHook;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::SetModuleDynamicImportHook(JSRuntime* rt, JS::ModuleDynamicImportHook func)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
rt->moduleDynamicImportHook = func;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
|
||||
HandleObject promise)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(referencingPrivate, promise);
|
||||
|
||||
return js::FinishDynamicModuleImport(cx, referencingPrivate, specifier, promise);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleObject module)
|
||||
|
|
|
@ -3050,6 +3050,25 @@ GetModuleMetadataHook(JSRuntime* rt);
|
|||
extern JS_PUBLIC_API(void)
|
||||
SetModuleMetadataHook(JSRuntime* rt, ModuleMetadataHook func);
|
||||
|
||||
using ModuleDynamicImportHook = bool (*)(JSContext* cx, HandleValue referencingPrivate,
|
||||
HandleString specifier, HandleObject promise);
|
||||
|
||||
/**
|
||||
* Get the HostResolveImportedModule hook for the runtime.
|
||||
*/
|
||||
extern JS_PUBLIC_API(ModuleDynamicImportHook)
|
||||
GetModuleDynamicImportHook(JSRuntime* rt);
|
||||
|
||||
/**
|
||||
* Set the HostResolveImportedModule hook for the runtime to the given function.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
SetModuleDynamicImportHook(JSRuntime* rt, ModuleDynamicImportHook func);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
FinishDynamicModuleImport(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
|
||||
HandleObject promise);
|
||||
|
||||
/**
|
||||
* Parse the given source buffer as a module in the scope of the current global
|
||||
* of cx and return a source text module record.
|
||||
|
|
|
@ -12,7 +12,7 @@ path = "lib.rs"
|
|||
baldrdash = { path = "../../wasm/cranelift" }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = {version = "0.39", default-features = false} # disable `logging` to reduce code size
|
||||
bindgen = {version = "0.43", default-features = false} # disable `logging` to reduce code size
|
||||
|
||||
# Uncomment this to enable perf support in release mode.
|
||||
#[profile.release]
|
||||
|
|
|
@ -5,8 +5,12 @@
|
|||
|
||||
/* global getModuleLoadPath setModuleLoadHook setModuleResolveHook setModuleMetadataHook */
|
||||
/* global getModulePrivate setModulePrivate parseModule os */
|
||||
/* global setModuleDynamicImportHook finishDynamicModuleImport abortDynamicModuleImport */
|
||||
|
||||
// A basic synchronous module loader for testing the shell.
|
||||
//
|
||||
// Supports loading files and 'javascript:' URLs that embed JS source text.
|
||||
|
||||
{
|
||||
// Save standard built-ins before scripts can modify them.
|
||||
const ArrayPrototypeJoin = Array.prototype.join;
|
||||
|
@ -21,16 +25,22 @@ const StringPrototypeStartsWith = String.prototype.startsWith;
|
|||
const StringPrototypeSubstring = String.prototype.substring;
|
||||
const ErrorClass = Error;
|
||||
|
||||
const JAVASCRIPT_SCHEME = "javascript:";
|
||||
|
||||
const ReflectLoader = new class {
|
||||
constructor() {
|
||||
this.registry = new Map();
|
||||
this.modulePaths = new Map();
|
||||
this.loadPath = getModuleLoadPath();
|
||||
}
|
||||
|
||||
isJavascriptURL(name) {
|
||||
return ReflectApply(StringPrototypeStartsWith, name, [JAVASCRIPT_SCHEME]);
|
||||
}
|
||||
|
||||
resolve(name, referencingInfo) {
|
||||
if (os.path.isAbsolute(name))
|
||||
if (this.isJavascriptURL(name) || os.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
|
||||
let loadPath = this.loadPath;
|
||||
|
||||
|
@ -67,6 +77,10 @@ const ReflectLoader = new class {
|
|||
}
|
||||
|
||||
normalize(path) {
|
||||
if (this.isJavascriptURL(path)) {
|
||||
return path;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Replace all forward slashes with backward slashes.
|
||||
// NB: It may be tempting to replace this loop with a call to
|
||||
|
@ -150,6 +164,10 @@ const ReflectLoader = new class {
|
|||
}
|
||||
|
||||
fetch(path) {
|
||||
if (this.isJavascriptURL(path)) {
|
||||
return ReflectApply(StringPrototypeSubstring, path, [JAVASCRIPT_SCHEME.length]);
|
||||
}
|
||||
|
||||
return os.file.readFile(path);
|
||||
}
|
||||
|
||||
|
@ -176,7 +194,7 @@ const ReflectLoader = new class {
|
|||
return this.loadAndExecute(path);
|
||||
}
|
||||
|
||||
["import"](name, referrer) {
|
||||
["import"](name, referencingInfo) {
|
||||
let path = this.resolve(name, null);
|
||||
return this.loadAndExecute(path);
|
||||
}
|
||||
|
@ -196,8 +214,8 @@ const ReflectLoader = new class {
|
|||
|
||||
setModuleLoadHook((path) => ReflectLoader.importRoot(path));
|
||||
|
||||
setModuleResolveHook((module, requestName) => {
|
||||
let path = ReflectLoader.resolve(requestName, module);
|
||||
setModuleResolveHook((referencingInfo, requestName) => {
|
||||
let path = ReflectLoader.resolve(requestName, referencingInfo);
|
||||
return ReflectLoader.loadAndParse(path);
|
||||
});
|
||||
|
||||
|
@ -205,5 +223,14 @@ setModuleMetadataHook((module, metaObject) => {
|
|||
ReflectLoader.populateImportMeta(module, metaObject);
|
||||
});
|
||||
|
||||
}
|
||||
setModuleDynamicImportHook((referencingInfo, specifier, promise) => {
|
||||
try {
|
||||
let path = ReflectLoader.resolve(specifier, referencingInfo);
|
||||
ReflectLoader.loadAndExecute(path);
|
||||
finishDynamicModuleImport(referencingInfo, specifier, promise);
|
||||
} catch (err) {
|
||||
abortDynamicModuleImport(referencingInfo, specifier, promise, err);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -193,6 +193,7 @@ enum GlobalAppSlot
|
|||
GlobalAppSlotModuleLoadHook, // Shell-specific; load a module graph
|
||||
GlobalAppSlotModuleResolveHook, // HostResolveImportedModule
|
||||
GlobalAppSlotModuleMetadataHook, // HostPopulateImportMeta
|
||||
GlobalAppSlotModuleDynamicImportHook, // HostImportModuleDynamically
|
||||
GlobalAppSlotCount
|
||||
};
|
||||
static_assert(GlobalAppSlotCount <= JSCLASS_GLOBAL_APPLICATION_SLOTS,
|
||||
|
@ -850,6 +851,32 @@ EnvironmentPreparer::invoke(HandleObject global, Closure& closure)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
RegisterScriptPathWithModuleLoader(JSContext* cx, HandleScript script, const char* filename)
|
||||
{
|
||||
// Set the private value associated with a script to a object containing the
|
||||
// script's filename so that the module loader can use it to resolve
|
||||
// relative imports.
|
||||
|
||||
RootedString path(cx, JS_NewStringCopyZ(cx, filename));
|
||||
if (!path) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject infoObject(cx, JS_NewPlainObject(cx));
|
||||
if (!infoObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue pathValue(cx, StringValue(path));
|
||||
if (!JS_DefineProperty(cx, infoObject, "path", pathValue, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::SetScriptPrivate(script, ObjectValue(*infoObject));
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
RunFile(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
|
||||
{
|
||||
|
@ -883,6 +910,10 @@ RunFile(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
|
|||
MOZ_ASSERT(script);
|
||||
}
|
||||
|
||||
if (!RegisterScriptPathWithModuleLoader(cx, script, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (dumpEntrainedVariables) {
|
||||
AnalyzeEntrainedVariables(cx, script);
|
||||
|
@ -919,6 +950,10 @@ RunBinAST(JSContext* cx, const char* filename, FILE* file)
|
|||
}
|
||||
}
|
||||
|
||||
if (!RegisterScriptPathWithModuleLoader(cx, script, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return JS_ExecuteScript(cx, script);
|
||||
}
|
||||
|
||||
|
@ -927,7 +962,6 @@ RunBinAST(JSContext* cx, const char* filename, FILE* file)
|
|||
static bool
|
||||
InitModuleLoader(JSContext* cx)
|
||||
{
|
||||
|
||||
// Decompress and evaluate the embedded module loader source to initialize
|
||||
// the module loader for the current compartment.
|
||||
|
||||
|
@ -4723,7 +4757,7 @@ SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
static JSObject*
|
||||
CallModuleResolveHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier)
|
||||
ShellModuleResolveHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier)
|
||||
{
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
RootedValue hookValue(cx, global->getReservedSlot(GlobalAppSlotModuleResolveHook));
|
||||
|
@ -4839,6 +4873,109 @@ ShellGetModulePrivate(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetModuleDynamicImportHook(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 1) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"setModuleDynamicImportHook", "0", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
|
||||
const char* typeName = InformalValueTypeName(args[0]);
|
||||
JS_ReportErrorASCII(cx, "expected hook function, got %s", typeName);
|
||||
return false;
|
||||
}
|
||||
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
global->setReservedSlot(GlobalAppSlotModuleDynamicImportHook, args[0]);
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
FinishDynamicModuleImport(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 3) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"finishDynamicModuleImport", "0", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[1].isString()) {
|
||||
return ReportArgumentTypeError(cx, args[1], "String");
|
||||
}
|
||||
|
||||
if (!args[2].isObject() || !args[2].toObject().is<PromiseObject>()) {
|
||||
return ReportArgumentTypeError(cx, args[2], "PromiseObject");
|
||||
}
|
||||
|
||||
RootedString specifier(cx, args[1].toString());
|
||||
Rooted<PromiseObject*> promise(cx, &args[2].toObject().as<PromiseObject>());
|
||||
|
||||
return js::FinishDynamicModuleImport(cx, args[0], specifier, promise);
|
||||
}
|
||||
|
||||
static bool
|
||||
AbortDynamicModuleImport(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() != 4) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
|
||||
"abortDynamicModuleImport", "0", "s");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args[1].isString()) {
|
||||
return ReportArgumentTypeError(cx, args[1], "String");
|
||||
}
|
||||
|
||||
if (!args[2].isObject() || !args[2].toObject().is<PromiseObject>()) {
|
||||
return ReportArgumentTypeError(cx, args[2], "PromiseObject");
|
||||
}
|
||||
|
||||
if (!args[3].isObject() || !args[3].toObject().is<ErrorObject>()) {
|
||||
return ReportArgumentTypeError(cx, args[3], "ErrorObject");
|
||||
}
|
||||
|
||||
RootedString specifier(cx, args[1].toString());
|
||||
Rooted<PromiseObject*> promise(cx, &args[2].toObject().as<PromiseObject>());
|
||||
Rooted<ErrorObject*> error(cx, &args[3].toObject().as<ErrorObject>());
|
||||
|
||||
Rooted<Value> value(cx, ObjectValue(*error));
|
||||
cx->setPendingException(value);
|
||||
return js::FinishDynamicModuleImport(cx, args[0], specifier, promise);
|
||||
}
|
||||
|
||||
static bool
|
||||
ShellModuleDynamicImportHook(JSContext* cx, HandleValue referencingPrivate, HandleString specifier,
|
||||
HandleObject promise)
|
||||
{
|
||||
Handle<GlobalObject*> global = cx->global();
|
||||
RootedValue hookValue(cx, global->getReservedSlot(GlobalAppSlotModuleDynamicImportHook));
|
||||
if (hookValue.isUndefined()) {
|
||||
JS_ReportErrorASCII(cx, "Module resolve hook not set");
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(hookValue.toObject().is<JSFunction>());
|
||||
|
||||
JS::AutoValueArray<3> args(cx);
|
||||
args[0].set(referencingPrivate);
|
||||
args[1].setString(specifier);
|
||||
args[2].setObject(*promise);
|
||||
|
||||
RootedValue result(cx);
|
||||
if (!JS_CallFunctionValue(cx, nullptr, hookValue, args, &result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -8059,7 +8196,7 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
|||
" module loader."),
|
||||
|
||||
JS_FN_HELP("setModuleResolveHook", SetModuleResolveHook, 1, 0,
|
||||
"setModuleResolveHook(function(module, specifier) {})",
|
||||
"setModuleResolveHook(function(referrer, specifier))",
|
||||
" Set the HostResolveImportedModule hook to |function|.\n"
|
||||
" This hook is used to look up a previously loaded module object. It should\n"
|
||||
" be implemented by the module loader."),
|
||||
|
@ -8070,6 +8207,22 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
|||
" This hook is used to create the metadata object returned by import.meta for\n"
|
||||
" a module. It should be implemented by the module loader."),
|
||||
|
||||
JS_FN_HELP("setModuleDynamicImportHook", SetModuleDynamicImportHook, 1, 0,
|
||||
"setModuleDynamicImportHook(function(referrer, specifier, promise))",
|
||||
" Set the HostImportModuleDynamically hook to |function|.\n"
|
||||
" This hook is used to dynamically import a module. It should\n"
|
||||
" be implemented by the module loader."),
|
||||
|
||||
JS_FN_HELP("finishDynamicModuleImport", FinishDynamicModuleImport, 3, 0,
|
||||
"finishDynamicModuleImport(referrer, specifier, promise)",
|
||||
" The module loader's dynamic import hook should call this when the module has"
|
||||
" been loaded successfully."),
|
||||
|
||||
JS_FN_HELP("abortDynamicModuleImport", AbortDynamicModuleImport, 4, 0,
|
||||
"abortDynamicModuleImport(referrer, specifier, promise, error)",
|
||||
" The module loader's dynamic import hook should call this when the module "
|
||||
" import has failed."),
|
||||
|
||||
JS_FN_HELP("setModulePrivate", ShellSetModulePrivate, 2, 0,
|
||||
"setModulePrivate(scriptObject, privateValue)",
|
||||
" Associate a private value with a module object.\n"),
|
||||
|
@ -10788,7 +10941,8 @@ main(int argc, char** argv, char** envp)
|
|||
|
||||
js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
|
||||
|
||||
JS::SetModuleResolveHook(cx->runtime(), CallModuleResolveHook);
|
||||
JS::SetModuleResolveHook(cx->runtime(), ShellModuleResolveHook);
|
||||
JS::SetModuleDynamicImportHook(cx->runtime(), ShellModuleDynamicImportHook);
|
||||
JS::SetModuleMetadataHook(cx->runtime(), CallModuleMetadataHook);
|
||||
|
||||
result = Shell(cx, &op, envp);
|
||||
|
|
|
@ -372,8 +372,8 @@ class JitTest:
|
|||
cmd += ['-f', libdir + inc]
|
||||
if self.skip_if_cond:
|
||||
cmd += ['-e', "if ({}) quit({})".format(self.skip_if_cond, self.SKIPPED_EXIT_STATUS)]
|
||||
cmd += ['--module-load-path', moduledir]
|
||||
if self.is_module:
|
||||
cmd += ['--module-load-path', moduledir]
|
||||
cmd += ['--module', path]
|
||||
elif self.is_binast:
|
||||
# In builds with BinAST, this will run the test file. In builds without,
|
||||
|
|
|
@ -3477,6 +3477,23 @@ js::GetModuleObjectForScript(JSScript* script)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Value
|
||||
js::FindScriptOrModulePrivateForScript(JSScript* script)
|
||||
{
|
||||
while (script) {
|
||||
ScriptSourceObject* sso = &script->scriptSourceUnwrap();
|
||||
Value value = sso->getPrivate();
|
||||
if (!value.isUndefined()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sso->introductionScript() != script);
|
||||
script = sso->introductionScript();
|
||||
}
|
||||
|
||||
return UndefinedValue();
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetThisValueForDebuggerMaybeOptimizedOut(JSContext* cx, AbstractFramePtr frame, jsbytecode* pc,
|
||||
MutableHandleValue res)
|
||||
|
|
|
@ -1182,7 +1182,11 @@ CreateObjectsForEnvironmentChain(JSContext* cx, AutoObjectVector& chain,
|
|||
HandleObject terminatingEnv,
|
||||
MutableHandleObject envObj);
|
||||
|
||||
ModuleObject* GetModuleObjectForScript(JSScript* script);
|
||||
ModuleObject*
|
||||
GetModuleObjectForScript(JSScript* script);
|
||||
|
||||
Value
|
||||
FindScriptOrModulePrivateForScript(JSScript* script);
|
||||
|
||||
ModuleEnvironmentObject* GetModuleEnvironmentForScript(JSScript* script);
|
||||
|
||||
|
|
|
@ -4724,7 +4724,23 @@ CASE(JSOP_IMPORTMETA)
|
|||
|
||||
PUSH_OBJECT(*metaObject);
|
||||
}
|
||||
END_CASE(JSOP_NEWTARGET)
|
||||
END_CASE(JSOP_IMPORTMETA)
|
||||
|
||||
CASE(JSOP_DYNAMIC_IMPORT)
|
||||
{
|
||||
ReservedRooted<Value> referencingPrivate(&rootValue0);
|
||||
referencingPrivate = FindScriptOrModulePrivateForScript(script);
|
||||
|
||||
ReservedRooted<Value> specifier(&rootValue1);
|
||||
POP_COPY_TO(specifier);
|
||||
|
||||
JSObject* promise = StartDynamicModuleImport(cx, referencingPrivate, specifier);
|
||||
if (!promise)
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*promise);
|
||||
}
|
||||
END_CASE(JSOP_DYNAMIC_IMPORT)
|
||||
|
||||
CASE(JSOP_SUPERFUN)
|
||||
{
|
||||
|
|
|
@ -2364,14 +2364,23 @@
|
|||
* Operands:
|
||||
* Stack: => import.meta
|
||||
*/ \
|
||||
macro(JSOP_IMPORTMETA, 232, "importmeta", NULL, 1, 0, 1, JOF_BYTE)
|
||||
macro(JSOP_IMPORTMETA, 232, "importmeta", NULL, 1, 0, 1, JOF_BYTE) \
|
||||
/*
|
||||
* Dynamic import of the module specified by the string value on the top of
|
||||
* the stack.
|
||||
*
|
||||
* Category: Variables and Scopes
|
||||
* Type: Modules
|
||||
* Operands:
|
||||
* Stack: arg => rval
|
||||
*/ \
|
||||
macro(JSOP_DYNAMIC_IMPORT, 233, "call-import", NULL, 1, 1, 1, JOF_BYTE)
|
||||
|
||||
/*
|
||||
* In certain circumstances it may be useful to "pad out" the opcode space to
|
||||
* a power of two. Use this macro to do so.
|
||||
*/
|
||||
#define FOR_EACH_TRAILING_UNUSED_OPCODE(macro) \
|
||||
macro(233) \
|
||||
macro(234) \
|
||||
macro(235) \
|
||||
macro(236) \
|
||||
|
|
|
@ -176,7 +176,8 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
|
|||
: js::StackFormat::SpiderMonkey),
|
||||
wasmInstances(mutexid::WasmRuntimeInstances),
|
||||
moduleResolveHook(),
|
||||
moduleMetadataHook()
|
||||
moduleMetadataHook(),
|
||||
moduleDynamicImportHook()
|
||||
{
|
||||
JS_COUNT_CTOR(JSRuntime);
|
||||
liveRuntimesCount++;
|
||||
|
|
|
@ -981,6 +981,10 @@ struct JSRuntime : public js::MallocProvider<JSRuntime>
|
|||
// HostGetImportMetaProperties and HostFinalizeImportMeta.
|
||||
js::MainThreadData<JS::ModuleMetadataHook> moduleMetadataHook;
|
||||
|
||||
// A hook that implements the abstract operation
|
||||
// HostImportModuleDynamically.
|
||||
js::MainThreadData<JS::ModuleDynamicImportHook> moduleDynamicImportHook;
|
||||
|
||||
public:
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
js::BinaryASTSupport& binast() {
|
||||
|
|
|
@ -1223,12 +1223,6 @@ ModuleScope::getEmptyEnvironmentShape(JSContext* cx)
|
|||
return EmptyEnvironmentShape(cx, cls, JSSLOT_FREE(cls), ModuleScopeEnvShapeFlags);
|
||||
}
|
||||
|
||||
JSScript*
|
||||
ModuleScope::script() const
|
||||
{
|
||||
return module()->script();
|
||||
}
|
||||
|
||||
static const uint32_t WasmInstanceEnvShapeFlags =
|
||||
BaseShape::NOT_EXTENSIBLE | BaseShape::DELEGATE;
|
||||
|
||||
|
|
|
@ -1027,8 +1027,6 @@ class ModuleScope : public Scope
|
|||
return data().module;
|
||||
}
|
||||
|
||||
JSScript* script() const;
|
||||
|
||||
static Shape* getEmptyEnvironmentShape(JSContext* cx);
|
||||
};
|
||||
|
||||
|
|
|
@ -2183,15 +2183,8 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
|
|||
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
|
||||
RootedString specifier(cx, args[1].toString());
|
||||
|
||||
JS::ModuleResolveHook moduleResolveHook = cx->runtime()->moduleResolveHook;
|
||||
if (!moduleResolveHook) {
|
||||
JS_ReportErrorASCII(cx, "Module resolve hook not set");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject result(cx);
|
||||
RootedValue referencingPrivate(cx, JS::GetModulePrivate(module));
|
||||
result = moduleResolveHook(cx, referencingPrivate, specifier);
|
||||
RootedObject result(cx, CallModuleResolveHook(cx, referencingPrivate, specifier));
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -154,13 +154,11 @@ AssertScopeMatchesEnvironment(Scope* scope, JSObject* originalEnv)
|
|||
MOZ_CRASH("NonSyntactic should not have a syntactic environment");
|
||||
break;
|
||||
|
||||
case ScopeKind::Module: {
|
||||
ModuleObject* module = &env->as<ModuleEnvironmentObject>().module();
|
||||
MOZ_ASSERT_IF(module->maybeScript(),
|
||||
module->script() == si.scope()->as<ModuleScope>().script());
|
||||
case ScopeKind::Module:
|
||||
MOZ_ASSERT(&env->as<ModuleEnvironmentObject>().module() ==
|
||||
si.scope()->as<ModuleScope>().module());
|
||||
env = &env->as<ModuleEnvironmentObject>().enclosingEnvironment();
|
||||
break;
|
||||
}
|
||||
|
||||
case ScopeKind::WasmInstance:
|
||||
env = &env->as<WasmInstanceEnvironmentObject>().enclosingEnvironment();
|
||||
|
|
|
@ -15,7 +15,7 @@ log = { version = "0.4.4", default-features = false, features = ["release_max_le
|
|||
env_logger = "0.5.6"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = {version = "0.39", default-features = false} # disable `logging` to reduce code size
|
||||
bindgen = {version = "0.43", default-features = false} # disable `logging` to reduce code size
|
||||
|
||||
# Uncomment this to enable perf support in release mode.
|
||||
#[profile.release]
|
||||
|
|
|
@ -112,6 +112,10 @@ cargo_extra_outputs = {
|
|||
'bzip2-1.0.6/randtable.o',
|
||||
'libbz2.a',
|
||||
],
|
||||
'clang-sys': [
|
||||
'common.rs',
|
||||
'dynamic.rs',
|
||||
],
|
||||
'cranelift-codegen': [
|
||||
'binemit-arm32.rs',
|
||||
'binemit-arm64.rs',
|
||||
|
|
|
@ -8,7 +8,7 @@ for (let [key, val] of Object.entries({
|
|||
|
||||
// Don't manually modify this line, as it is automatically replaced on merge day
|
||||
// by the gecko_migration.py script.
|
||||
WEAVE_VERSION: "1.66.0",
|
||||
WEAVE_VERSION: "1.67.0",
|
||||
|
||||
// Sync Server API version that the client supports.
|
||||
SYNC_API_VERSION: "1.5",
|
||||
|
|
|
@ -78,7 +78,7 @@ void = "1.0.2"
|
|||
[build-dependencies]
|
||||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
bindgen = { version = "0.39", optional = true, default-features = false }
|
||||
bindgen = { version = "0.43", optional = true, default-features = false }
|
||||
regex = {version = "1.0", optional = true}
|
||||
walkdir = "2.1.4"
|
||||
toml = {version = "0.4.5", optional = true, default-features = false}
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
loader: taskgraph.loader.transform:loader
|
||||
|
||||
transforms:
|
||||
- taskgraph.transforms.bouncer_locations_breakpoint:transforms
|
||||
- taskgraph.transforms.task:transforms
|
||||
|
||||
job-defaults:
|
||||
description: nightly bouncer locations breakpoint job
|
||||
attributes:
|
||||
build_platform: linux64-nightly
|
||||
nightly: true
|
||||
worker-type:
|
||||
by-project:
|
||||
mozilla-central: null-provisioner/human-breakpoint
|
||||
default: invalid/invalid
|
||||
worker:
|
||||
implementation: bouncer-locations-breakpoint
|
||||
run-on-projects: ['mozilla-central']
|
||||
treeherder:
|
||||
symbol: BncLoc-Br
|
||||
kind: other
|
||||
tier: 2
|
||||
|
||||
jobs:
|
||||
firefox:
|
||||
treeherder:
|
||||
platform: firefox-release/opt
|
|
@ -8,6 +8,9 @@ transforms:
|
|||
- taskgraph.transforms.bouncer_locations:transforms
|
||||
- taskgraph.transforms.task:transforms
|
||||
|
||||
kind-dependencies:
|
||||
- bouncer-locations-breakpoint
|
||||
|
||||
job-defaults:
|
||||
description: nightly bouncer locations job
|
||||
attributes:
|
||||
|
|
|
@ -311,6 +311,10 @@ bouncer-locations
|
|||
-----------------
|
||||
Updates nightly bouncer locations for version bump
|
||||
|
||||
bouncer-locations-breakpoint
|
||||
----------------------------
|
||||
Human breakpoint to block the running of the bouncer locations job until shippable builds are implemented
|
||||
|
||||
release-bouncer-check
|
||||
---------------------
|
||||
Checks Bouncer (download.mozilla.org) uptake as part of the release tasks.
|
||||
|
|
|
@ -28,6 +28,12 @@ def make_task_worker(config, jobs):
|
|||
)
|
||||
|
||||
job['worker']['bouncer-products'] = job['bouncer-products']
|
||||
|
||||
del job['bouncer-products']
|
||||
|
||||
# chain the breakpoint as dependency to this task
|
||||
dependencies = {}
|
||||
for dep_task in config.kind_dependencies_tasks:
|
||||
dependencies[dep_task.kind] = dep_task.label
|
||||
|
||||
job.setdefault('dependencies', {}).update(dependencies)
|
||||
yield job
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
import logging
|
||||
|
||||
from taskgraph.transforms.base import TransformSequence
|
||||
from taskgraph.util.schema import resolve_keyed_by
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
transforms = TransformSequence()
|
||||
|
||||
|
||||
@transforms.add
|
||||
def make_task_worker(config, jobs):
|
||||
for job in jobs:
|
||||
resolve_keyed_by(
|
||||
job, 'worker-type', item_name=job['name'], project=config.params['project']
|
||||
)
|
||||
job['worker']['payload'] = {}
|
||||
yield job
|
|
@ -571,6 +571,9 @@ task_description_schema = Schema({
|
|||
}, {
|
||||
Required('implementation'): 'bouncer-locations',
|
||||
Required('bouncer-products'): [basestring],
|
||||
}, {
|
||||
Required('implementation'): 'bouncer-locations-breakpoint',
|
||||
Required('payload'): object,
|
||||
}, {
|
||||
Required('implementation'): 'bouncer-submission',
|
||||
Required('locales'): [basestring],
|
||||
|
@ -1215,6 +1218,11 @@ def build_bouncer_locations_payload(config, task, task_def):
|
|||
}
|
||||
|
||||
|
||||
@payload_builder('bouncer-locations-breakpoint')
|
||||
def build_bouncer_locations_breakpoint_payload(config, task, task_def):
|
||||
task_def['payload'] = task['worker']['payload']
|
||||
|
||||
|
||||
@payload_builder('bouncer-submission')
|
||||
def build_bouncer_submission_payload(config, task, task_def):
|
||||
worker = task['worker']
|
||||
|
|
|
@ -51,7 +51,18 @@ Documentation
|
|||
* [Enabling trace logs](https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/TraceLogs.html)
|
||||
* [Analyzing crash data from Firefox](https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/CrashReports.html)
|
||||
|
||||
* [Contributing](https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/index.html#for-developers)
|
||||
* [Contributing](https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/#for-developers)
|
||||
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
geckodriver’s canonical source code can be found in [mozilla-central].
|
||||
We only use this GitHub repository for issue tracking and making releases.
|
||||
See our [contribution documentation] for more information.
|
||||
|
||||
[mozilla-central]: https://hg.mozilla.org/mozilla-central/file/tip/testing/geckodriver
|
||||
[contribution documentation]: https://firefox-source-docs.mozilla.org/testing/geckodriver/geckodriver/#for-developers
|
||||
|
||||
|
||||
Contact
|
||||
|
|
|
@ -73,7 +73,7 @@ promise_test(() => {
|
|||
}, "Stray argument");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.compile(buffer);
|
||||
buffer[0] = 1;
|
||||
|
|
|
@ -103,7 +103,7 @@ promise_test(t => {
|
|||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
const buffer = new Uint8Array(new WasmModuleBuilder().toBuffer());
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.instantiate(buffer);
|
||||
buffer[0] = 1;
|
||||
|
|
|
@ -133,18 +133,14 @@ const instanceTestFactory = [
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_d)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.setTableLength(1);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
builder.addGlobal(kWasmI32, true)
|
||||
|
@ -190,7 +186,6 @@ const instanceTestFactory = [
|
|||
kExprGetGlobal,
|
||||
index,
|
||||
kExprReturn,
|
||||
kExprEnd,
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
|
|
|
@ -92,18 +92,14 @@ test(() => {
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.setTableLength(1);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
builder.addGlobal(kWasmI32, true)
|
||||
|
|
|
@ -9,15 +9,11 @@ setup(() => {
|
|||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_d)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.addBody([])
|
||||
.exportFunc();
|
||||
|
||||
const buffer = builder.toBuffer()
|
||||
|
|
|
@ -21,7 +21,7 @@ var kWasmH1 = 0x61;
|
|||
var kWasmH2 = 0x73;
|
||||
var kWasmH3 = 0x6d;
|
||||
|
||||
var kWasmV0 = 1;
|
||||
var kWasmV0 = 0x1;
|
||||
var kWasmV1 = 0;
|
||||
var kWasmV2 = 0;
|
||||
var kWasmV3 = 0;
|
||||
|
@ -65,10 +65,15 @@ let kCodeSectionCode = 10; // Function code
|
|||
let kDataSectionCode = 11; // Data segments
|
||||
let kNameSectionCode = 12; // Name section (encoded as string)
|
||||
|
||||
// Name section types
|
||||
let kModuleNameCode = 0;
|
||||
let kFunctionNamesCode = 1;
|
||||
let kLocalNamesCode = 2;
|
||||
|
||||
let kWasmFunctionTypeForm = 0x60;
|
||||
let kWasmAnyFunctionTypeForm = 0x70;
|
||||
|
||||
let kResizableMaximumFlag = 1;
|
||||
let kHasMaximumFlag = 1;
|
||||
|
||||
// Function declaration flags
|
||||
let kDeclFunctionName = 0x01;
|
||||
|
@ -82,7 +87,6 @@ let kWasmI32 = 0x7f;
|
|||
let kWasmI64 = 0x7e;
|
||||
let kWasmF32 = 0x7d;
|
||||
let kWasmF64 = 0x7c;
|
||||
let kWasmS128 = 0x7b;
|
||||
|
||||
let kExternalFunction = 0;
|
||||
let kExternalTable = 1;
|
||||
|
@ -104,7 +108,7 @@ let kSig_i_dd = makeSig([kWasmF64, kWasmF64], [kWasmI32]);
|
|||
let kSig_v_v = makeSig([], []);
|
||||
let kSig_i_v = makeSig([], [kWasmI32]);
|
||||
let kSig_l_v = makeSig([], [kWasmI64]);
|
||||
let kSig_f_v = makeSig([], [kWasmF64]);
|
||||
let kSig_f_v = makeSig([], [kWasmF32]);
|
||||
let kSig_d_v = makeSig([], [kWasmF64]);
|
||||
let kSig_v_i = makeSig([kWasmI32], []);
|
||||
let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
|
||||
|
@ -113,7 +117,6 @@ let kSig_v_l = makeSig([kWasmI64], []);
|
|||
let kSig_v_d = makeSig([kWasmF64], []);
|
||||
let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
|
||||
let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
|
||||
let kSig_s_v = makeSig([], [kWasmS128]);
|
||||
|
||||
function makeSig(params, results) {
|
||||
return {params: params, results: results};
|
||||
|
@ -191,7 +194,7 @@ let kExprI64StoreMem8 = 0x3c;
|
|||
let kExprI64StoreMem16 = 0x3d;
|
||||
let kExprI64StoreMem32 = 0x3e;
|
||||
let kExprMemorySize = 0x3f;
|
||||
let kExprGrowMemory = 0x40;
|
||||
let kExprMemoryGrow = 0x40;
|
||||
let kExprI32Eqz = 0x45;
|
||||
let kExprI32Eq = 0x46;
|
||||
let kExprI32Ne = 0x47;
|
||||
|
@ -339,36 +342,34 @@ let kTrapMsgs = [
|
|||
];
|
||||
|
||||
function assertTraps(trap, code) {
|
||||
var threwException = true;
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
threwException = false;
|
||||
} catch (e) {
|
||||
assertEquals("object", typeof e);
|
||||
assertEquals(kTrapMsgs[trap], e.message);
|
||||
// Success.
|
||||
return;
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
throw new MjsUnitAssertionError("Did not trap, expected: " + kTrapMsgs[trap]);
|
||||
} catch (e) {
|
||||
assertEquals('object', typeof e);
|
||||
assertEquals(kTrapMsgs[trap], e.message);
|
||||
// Success.
|
||||
return;
|
||||
}
|
||||
throw new MjsUnitAssertionError('Did not trap, expected: ' + kTrapMsgs[trap]);
|
||||
}
|
||||
|
||||
function assertWasmThrows(value, code) {
|
||||
assertEquals("number", typeof(value));
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
} catch (e) {
|
||||
assertEquals("number", typeof e);
|
||||
assertEquals(value, e);
|
||||
// Success.
|
||||
return;
|
||||
assertEquals('number', typeof value);
|
||||
try {
|
||||
if (typeof code === 'function') {
|
||||
code();
|
||||
} else {
|
||||
eval(code);
|
||||
}
|
||||
throw new MjsUnitAssertionError("Did not throw at all, expected: " + value);
|
||||
} catch (e) {
|
||||
assertEquals('number', typeof e);
|
||||
assertEquals(value, e);
|
||||
// Success.
|
||||
return;
|
||||
}
|
||||
throw new MjsUnitAssertionError('Did not throw, expected: ' + value);
|
||||
}
|
||||
|
|
|
@ -69,12 +69,14 @@ class Binary extends Array {
|
|||
// Emit section name.
|
||||
this.emit_u8(section_code);
|
||||
// Emit the section to a temporary buffer: its full length isn't know yet.
|
||||
let section = new Binary;
|
||||
const section = new Binary;
|
||||
content_generator(section);
|
||||
// Emit section length.
|
||||
this.emit_u32v(section.length);
|
||||
// Copy the temporary buffer.
|
||||
this.push(...section);
|
||||
for (const b of section) {
|
||||
this.push(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +88,15 @@ class WasmFunctionBuilder {
|
|||
this.body = [];
|
||||
}
|
||||
|
||||
numLocalNames() {
|
||||
if (this.local_names === undefined) return 0;
|
||||
let num_local_names = 0;
|
||||
for (let loc_name of this.local_names) {
|
||||
if (loc_name !== undefined) ++num_local_names;
|
||||
}
|
||||
return num_local_names;
|
||||
}
|
||||
|
||||
exportAs(name) {
|
||||
this.module.addExport(name, this.index);
|
||||
return this;
|
||||
|
@ -97,12 +108,40 @@ class WasmFunctionBuilder {
|
|||
}
|
||||
|
||||
addBody(body) {
|
||||
for (let b of body) {
|
||||
if (typeof b !== 'number' || (b & (~0xFF)) !== 0 )
|
||||
throw new Error('invalid body (entries must be 8 bit numbers): ' + body);
|
||||
}
|
||||
this.body = body.slice();
|
||||
// Automatically add the end for the function block to the body.
|
||||
this.body.push(kExprEnd);
|
||||
return this;
|
||||
}
|
||||
|
||||
addBodyWithEnd(body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
addLocals(locals) {
|
||||
this.locals = locals;
|
||||
getNumLocals() {
|
||||
let total_locals = 0;
|
||||
for (let l of this.locals || []) {
|
||||
for (let type of ["i32", "i64", "f32", "f64"]) {
|
||||
total_locals += l[type + "_count"] || 0;
|
||||
}
|
||||
}
|
||||
return total_locals;
|
||||
}
|
||||
|
||||
addLocals(locals, names) {
|
||||
const old_num_locals = this.getNumLocals();
|
||||
if (!this.locals) this.locals = []
|
||||
this.locals.push(locals);
|
||||
if (names) {
|
||||
if (!this.local_names) this.local_names = [];
|
||||
const missing_names = old_num_locals - this.local_names.length;
|
||||
this.local_names.push(...new Array(missing_names), ...names);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -133,10 +172,10 @@ class WasmModuleBuilder {
|
|||
this.exports = [];
|
||||
this.globals = [];
|
||||
this.functions = [];
|
||||
this.function_table = [];
|
||||
this.function_table_length = 0;
|
||||
this.function_table_inits = [];
|
||||
this.segments = [];
|
||||
this.table_length_min = 0;
|
||||
this.table_length_max = undefined;
|
||||
this.element_segments = [];
|
||||
this.data_segments = [];
|
||||
this.explicit = [];
|
||||
this.num_imported_funcs = 0;
|
||||
this.num_imported_globals = 0;
|
||||
|
@ -158,6 +197,22 @@ class WasmModuleBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
stringToBytes(name) {
|
||||
var result = new Binary();
|
||||
result.emit_u32v(name.length);
|
||||
for (var i = 0; i < name.length; i++) {
|
||||
result.emit_u8(name.charCodeAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
addCustomSection(name, bytes) {
|
||||
name = this.stringToBytes(name);
|
||||
var length = new Binary();
|
||||
length.emit_u32v(name.length + bytes.length);
|
||||
this.explicit.push([0, ...length, ...name, ...bytes]);
|
||||
}
|
||||
|
||||
addType(type) {
|
||||
// TODO: canonicalize types?
|
||||
this.types.push(type);
|
||||
|
@ -180,15 +235,21 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
addImport(module = "", name, type) {
|
||||
if (this.functions.length != 0) {
|
||||
throw new Error('Imported functions must be declared before local ones');
|
||||
}
|
||||
let type_index = (typeof type) == "number" ? type : this.addType(type);
|
||||
this.imports.push({module: module, name: name, kind: kExternalFunction,
|
||||
type: type_index});
|
||||
return this.num_imported_funcs++;
|
||||
}
|
||||
|
||||
addImportedGlobal(module = "", name, type) {
|
||||
addImportedGlobal(module = "", name, type, mutable = false) {
|
||||
if (this.globals.length != 0) {
|
||||
throw new Error('Imported globals must be declared before local ones');
|
||||
}
|
||||
let o = {module: module, name: name, kind: kExternalGlobal, type: type,
|
||||
mutable: false}
|
||||
mutable: mutable};
|
||||
this.imports.push(o);
|
||||
return this.num_imported_globals++;
|
||||
}
|
||||
|
@ -217,32 +278,51 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
addDataSegment(addr, data, is_global = false) {
|
||||
this.segments.push({addr: addr, data: data, is_global: is_global});
|
||||
return this.segments.length - 1;
|
||||
this.data_segments.push({addr: addr, data: data, is_global: is_global});
|
||||
return this.data_segments.length - 1;
|
||||
}
|
||||
|
||||
exportMemoryAs(name) {
|
||||
this.exports.push({name: name, kind: kExternalMemory, index: 0});
|
||||
}
|
||||
|
||||
addFunctionTableInit(base, is_global, array) {
|
||||
this.function_table_inits.push({base: base, is_global: is_global,
|
||||
addElementSegment(base, is_global, array, is_import = false) {
|
||||
this.element_segments.push({base: base, is_global: is_global,
|
||||
array: array});
|
||||
if (!is_global) {
|
||||
var length = base + array.length;
|
||||
if (length > this.function_table_length) {
|
||||
this.function_table_length = length;
|
||||
if (length > this.table_length_min && !is_import) {
|
||||
this.table_length_min = length;
|
||||
}
|
||||
if (length > this.table_length_max && !is_import) {
|
||||
this.table_length_max = length;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
appendToTable(array) {
|
||||
return this.addFunctionTableInit(this.function_table.length, false, array);
|
||||
for (let n of array) {
|
||||
if (typeof n != 'number')
|
||||
throw new Error('invalid table (entries have to be numbers): ' + array);
|
||||
}
|
||||
return this.addElementSegment(this.table_length_min, false, array);
|
||||
}
|
||||
|
||||
setFunctionTableLength(length) {
|
||||
this.function_table_length = length;
|
||||
setTableBounds(min, max) {
|
||||
this.table_length_min = min;
|
||||
this.table_length_max = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
setTableLength(length) {
|
||||
this.table_length_min = length;
|
||||
this.table_length_max = length;
|
||||
return this;
|
||||
}
|
||||
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -305,40 +385,39 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add functions declarations
|
||||
let has_names = false;
|
||||
let names = false;
|
||||
if (wasm.functions.length > 0) {
|
||||
if (debug) print("emitting function decls @ " + binary.length);
|
||||
binary.emit_section(kFunctionSectionCode, section => {
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
has_names = has_names || (func.name != undefined &&
|
||||
func.name.length > 0);
|
||||
section.emit_u32v(func.type_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add function_table.
|
||||
if (wasm.function_table_length > 0) {
|
||||
// Add table section
|
||||
if (wasm.table_length_min > 0) {
|
||||
if (debug) print("emitting table @ " + binary.length);
|
||||
binary.emit_section(kTableSectionCode, section => {
|
||||
section.emit_u8(1); // one table entry
|
||||
section.emit_u8(kWasmAnyFunctionTypeForm);
|
||||
section.emit_u8(1);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
section.emit_u32v(wasm.function_table_length);
|
||||
const max = wasm.table_length_max;
|
||||
const has_max = max !== undefined;
|
||||
section.emit_u8(has_max ? kHasMaximumFlag : 0);
|
||||
section.emit_u32v(wasm.table_length_min);
|
||||
if (has_max) section.emit_u32v(max);
|
||||
});
|
||||
}
|
||||
|
||||
// Add memory section
|
||||
if (wasm.memory != undefined) {
|
||||
if (wasm.memory !== undefined) {
|
||||
if (debug) print("emitting memory @ " + binary.length);
|
||||
binary.emit_section(kMemorySectionCode, section => {
|
||||
section.emit_u8(1); // one memory entry
|
||||
section.emit_u32v(kResizableMaximumFlag);
|
||||
const has_max = wasm.memory.max !== undefined;
|
||||
section.emit_u8(has_max ? kHasMaximumFlag : 0);
|
||||
section.emit_u32v(wasm.memory.min);
|
||||
section.emit_u32v(wasm.memory.max);
|
||||
if (has_max) section.emit_u32v(wasm.memory.max);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -359,7 +438,7 @@ class WasmModuleBuilder {
|
|||
break;
|
||||
case kWasmI64:
|
||||
section.emit_u8(kExprI64Const);
|
||||
section.emit_u8(global.init);
|
||||
section.emit_u32v(global.init);
|
||||
break;
|
||||
case kWasmF32:
|
||||
section.emit_u8(kExprF32Const);
|
||||
|
@ -393,7 +472,7 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add export table.
|
||||
var mem_export = (wasm.memory != undefined && wasm.memory.exp);
|
||||
var mem_export = (wasm.memory !== undefined && wasm.memory.exp);
|
||||
var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
|
||||
if (exports_count > 0) {
|
||||
if (debug) print("emitting exports @ " + binary.length);
|
||||
|
@ -413,22 +492,22 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add start function section.
|
||||
if (wasm.start_index != undefined) {
|
||||
if (wasm.start_index !== undefined) {
|
||||
if (debug) print("emitting start function @ " + binary.length);
|
||||
binary.emit_section(kStartSectionCode, section => {
|
||||
section.emit_u32v(wasm.start_index);
|
||||
});
|
||||
}
|
||||
|
||||
// Add table elements.
|
||||
if (wasm.function_table_inits.length > 0) {
|
||||
if (debug) print("emitting table @ " + binary.length);
|
||||
// Add element segments
|
||||
if (wasm.element_segments.length > 0) {
|
||||
if (debug) print("emitting element segments @ " + binary.length);
|
||||
binary.emit_section(kElementSectionCode, section => {
|
||||
var inits = wasm.function_table_inits;
|
||||
var inits = wasm.element_segments;
|
||||
section.emit_u32v(inits.length);
|
||||
section.emit_u8(0); // table index
|
||||
|
||||
for (let init of inits) {
|
||||
section.emit_u8(0); // table index
|
||||
if (init.is_global) {
|
||||
section.emit_u8(kExprGetGlobal);
|
||||
} else {
|
||||
|
@ -453,9 +532,7 @@ class WasmModuleBuilder {
|
|||
for (let func of wasm.functions) {
|
||||
// Function body length will be patched later.
|
||||
let local_decls = [];
|
||||
let l = func.locals;
|
||||
if (l != undefined) {
|
||||
let local_decls_count = 0;
|
||||
for (let l of func.locals || []) {
|
||||
if (l.i32_count > 0) {
|
||||
local_decls.push({count: l.i32_count, type: kWasmI32});
|
||||
}
|
||||
|
@ -485,11 +562,11 @@ class WasmModuleBuilder {
|
|||
}
|
||||
|
||||
// Add data segments.
|
||||
if (wasm.segments.length > 0) {
|
||||
if (wasm.data_segments.length > 0) {
|
||||
if (debug) print("emitting data segments @ " + binary.length);
|
||||
binary.emit_section(kDataSectionCode, section => {
|
||||
section.emit_u32v(wasm.segments.length);
|
||||
for (let seg of wasm.segments) {
|
||||
section.emit_u32v(wasm.data_segments.length);
|
||||
for (let seg of wasm.data_segments) {
|
||||
section.emit_u8(0); // linear memory index 0
|
||||
if (seg.is_global) {
|
||||
// initializer is a global variable
|
||||
|
@ -513,21 +590,50 @@ class WasmModuleBuilder {
|
|||
binary.emit_bytes(exp);
|
||||
}
|
||||
|
||||
// Add function names.
|
||||
if (has_names) {
|
||||
if (debug) print("emitting names @ " + binary.length);
|
||||
// Add names.
|
||||
let num_function_names = 0;
|
||||
let num_functions_with_local_names = 0;
|
||||
for (let func of wasm.functions) {
|
||||
if (func.name !== undefined) ++num_function_names;
|
||||
if (func.numLocalNames() > 0) ++num_functions_with_local_names;
|
||||
}
|
||||
if (num_function_names > 0 || num_functions_with_local_names > 0 ||
|
||||
wasm.name !== undefined) {
|
||||
if (debug) print('emitting names @ ' + binary.length);
|
||||
binary.emit_section(kUnknownSectionCode, section => {
|
||||
section.emit_string("name");
|
||||
var count = wasm.functions.length + wasm.num_imported_funcs;
|
||||
section.emit_u32v(count);
|
||||
for (var i = 0; i < wasm.num_imported_funcs; i++) {
|
||||
section.emit_u8(0); // empty string
|
||||
section.emit_u8(0); // local names count == 0
|
||||
section.emit_string('name');
|
||||
// Emit module name.
|
||||
if (wasm.name !== undefined) {
|
||||
section.emit_section(kModuleNameCode, name_section => {
|
||||
name_section.emit_string(wasm.name);
|
||||
});
|
||||
}
|
||||
for (let func of wasm.functions) {
|
||||
var name = func.name == undefined ? "" : func.name;
|
||||
section.emit_string(name);
|
||||
section.emit_u8(0); // local names count == 0
|
||||
// Emit function names.
|
||||
if (num_function_names > 0) {
|
||||
section.emit_section(kFunctionNamesCode, name_section => {
|
||||
name_section.emit_u32v(num_function_names);
|
||||
for (let func of wasm.functions) {
|
||||
if (func.name === undefined) continue;
|
||||
name_section.emit_u32v(func.index);
|
||||
name_section.emit_string(func.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
// Emit local names.
|
||||
if (num_functions_with_local_names > 0) {
|
||||
section.emit_section(kLocalNamesCode, name_section => {
|
||||
name_section.emit_u32v(num_functions_with_local_names);
|
||||
for (let func of wasm.functions) {
|
||||
if (func.numLocalNames() == 0) continue;
|
||||
name_section.emit_u32v(func.index);
|
||||
name_section.emit_u32v(func.numLocalNames());
|
||||
for (let i = 0; i < func.local_names.length; ++i) {
|
||||
if (func.local_names[i] === undefined) continue;
|
||||
name_section.emit_u32v(i);
|
||||
name_section.emit_string(func.local_names[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -544,12 +650,21 @@ class WasmModuleBuilder {
|
|||
if ((typeof val) == "string") val = val.charCodeAt(0);
|
||||
view[i] = val | 0;
|
||||
}
|
||||
return new Uint8Array(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
instantiate(...args) {
|
||||
instantiate(ffi) {
|
||||
let module = new WebAssembly.Module(this.toBuffer());
|
||||
let instance = new WebAssembly.Instance(module, ...args);
|
||||
let instance = new WebAssembly.Instance(module, ffi);
|
||||
return instance;
|
||||
}
|
||||
|
||||
asyncInstantiate(ffi) {
|
||||
return WebAssembly.instantiate(this.toBuffer(), ffi)
|
||||
.then(({module, instance}) => instance);
|
||||
}
|
||||
|
||||
toModule(debug = false) {
|
||||
return new WebAssembly.Module(this.toBuffer(debug));
|
||||
}
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"git": {
|
||||
"sha1": "a242c51e6ff0d4cc27940a3927e713e8dff82c5f"
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "bindgen"
|
||||
version = "0.39.0"
|
||||
version = "0.43.0"
|
||||
authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
|
||||
build = "build.rs"
|
||||
include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
|
||||
|
@ -36,13 +36,13 @@ doc = false
|
|||
version = "1.0.3"
|
||||
|
||||
[dependencies.cexpr]
|
||||
version = "0.2"
|
||||
version = "0.3.3"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies.clang-sys]
|
||||
version = "0.23"
|
||||
version = "0.26"
|
||||
features = ["runtime", "clang_6_0"]
|
||||
|
||||
[dependencies.clap]
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::ffi::{CStr, CString};
|
|||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::os::raw::{c_char, c_int, c_uint, c_ulong};
|
||||
use std::os::raw::{c_char, c_int, c_uint, c_ulong, c_longlong, c_ulonglong};
|
||||
|
||||
/// A cursor into the Clang AST, pointing to an AST node.
|
||||
///
|
||||
|
@ -940,6 +940,7 @@ impl Type {
|
|||
CXType_RValueReference |
|
||||
CXType_LValueReference |
|
||||
CXType_MemberPointer |
|
||||
CXType_BlockPointer |
|
||||
CXType_ObjCObjectPointer => {
|
||||
let ret = Type {
|
||||
x: unsafe { clang_getPointeeType(self.x) },
|
||||
|
@ -1786,13 +1787,34 @@ impl EvalResult {
|
|||
}
|
||||
|
||||
/// Try to get back the result as an integer.
|
||||
pub fn as_int(&self) -> Option<i32> {
|
||||
match self.kind() {
|
||||
CXEval_Int => {
|
||||
Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i32)
|
||||
}
|
||||
_ => None,
|
||||
pub fn as_int(&self) -> Option<i64> {
|
||||
if self.kind() != CXEval_Int {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !clang_EvalResult_isUnsignedInt::is_loaded() {
|
||||
// FIXME(emilio): There's no way to detect underflow here, and clang
|
||||
// will just happily give us a value.
|
||||
return Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i64)
|
||||
}
|
||||
|
||||
if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
|
||||
let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
|
||||
if value > i64::max_value() as c_ulonglong {
|
||||
return None;
|
||||
}
|
||||
|
||||
return Some(value as i64)
|
||||
}
|
||||
|
||||
let value = unsafe { clang_EvalResult_getAsLongLong(self.x) };
|
||||
if value > i64::max_value() as c_longlong {
|
||||
return None;
|
||||
}
|
||||
if value < i64::min_value() as c_longlong {
|
||||
return None;
|
||||
}
|
||||
Some(value as i64)
|
||||
}
|
||||
|
||||
/// Evaluates the expression as a literal string, that may or may not be
|
||||
|
|
|
@ -59,14 +59,14 @@ pub mod attributes {
|
|||
|
||||
/// Generates a proper type for a field or type with a given `Layout`, that is,
|
||||
/// a type with the correct size and alignment restrictions.
|
||||
pub fn blob(layout: Layout) -> quote::Tokens {
|
||||
pub fn blob(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
|
||||
let opaque = layout.opaque();
|
||||
|
||||
// FIXME(emilio, #412): We fall back to byte alignment, but there are
|
||||
// some things that legitimately are more than 8-byte aligned.
|
||||
//
|
||||
// Eventually we should be able to `unwrap` here, but...
|
||||
let ty_name = match opaque.known_rust_type_for_array() {
|
||||
let ty_name = match opaque.known_rust_type_for_array(ctx) {
|
||||
Some(ty) => ty,
|
||||
None => {
|
||||
warn!("Found unknown alignment on code generation!");
|
||||
|
@ -76,7 +76,7 @@ pub fn blob(layout: Layout) -> quote::Tokens {
|
|||
|
||||
let ty_name = Term::new(ty_name, Span::call_site());
|
||||
|
||||
let data_len = opaque.array_size().unwrap_or(layout.size);
|
||||
let data_len = opaque.array_size(ctx).unwrap_or(layout.size);
|
||||
|
||||
if data_len == 1 {
|
||||
quote! {
|
||||
|
@ -90,8 +90,8 @@ pub fn blob(layout: Layout) -> quote::Tokens {
|
|||
}
|
||||
|
||||
/// Integer type of the same size as the given `Layout`.
|
||||
pub fn integer_type(layout: Layout) -> Option<quote::Tokens> {
|
||||
let name = Layout::known_type_for_size(layout.size)?;
|
||||
pub fn integer_type(ctx: &BindgenContext, layout: Layout) -> Option<quote::Tokens> {
|
||||
let name = Layout::known_type_for_size(ctx, layout.size)?;
|
||||
let name = Term::new(name, Span::call_site());
|
||||
Some(quote! { #name })
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
|
|||
pub mod ast_ty {
|
||||
use ir::context::BindgenContext;
|
||||
use ir::function::FunctionSig;
|
||||
use ir::layout::Layout;
|
||||
use ir::ty::FloatKind;
|
||||
use quote;
|
||||
use proc_macro2;
|
||||
|
@ -144,22 +145,44 @@ pub mod ast_ty {
|
|||
pub fn float_kind_rust_type(
|
||||
ctx: &BindgenContext,
|
||||
fk: FloatKind,
|
||||
layout: Option<Layout>,
|
||||
) -> quote::Tokens {
|
||||
// TODO: we probably should just take the type layout into
|
||||
// account?
|
||||
// TODO: we probably should take the type layout into account more
|
||||
// often?
|
||||
//
|
||||
// Also, maybe this one shouldn't be the default?
|
||||
//
|
||||
// FIXME: `c_longdouble` doesn't seem to be defined in some
|
||||
// systems, so we use `c_double` directly.
|
||||
match (fk, ctx.options().convert_floats) {
|
||||
(FloatKind::Float, true) => quote! { f32 },
|
||||
(FloatKind::Double, true) |
|
||||
(FloatKind::LongDouble, true) => quote! { f64 },
|
||||
(FloatKind::Double, true) => quote! { f64 },
|
||||
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
|
||||
(FloatKind::Double, false) |
|
||||
(FloatKind::LongDouble, false) => raw_type(ctx, "c_double"),
|
||||
(FloatKind::Float128, _) => quote! { [u8; 16] },
|
||||
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
|
||||
(FloatKind::LongDouble, _) => {
|
||||
match layout {
|
||||
Some(layout) => {
|
||||
match layout.size {
|
||||
4 => quote! { f32 },
|
||||
8 => quote! { f64 },
|
||||
// TODO(emilio): If rust ever gains f128 we should
|
||||
// use it here and below.
|
||||
_ => super::integer_type(ctx, layout).unwrap_or(quote! { f64 }),
|
||||
}
|
||||
}
|
||||
None => {
|
||||
debug_assert!(
|
||||
false,
|
||||
"How didn't we know the layout for a primitive type?"
|
||||
);
|
||||
quote! { f64 }
|
||||
}
|
||||
}
|
||||
}
|
||||
(FloatKind::Float128, _) => {
|
||||
if ctx.options().rust_features.i128_and_u128 {
|
||||
quote! { u128 }
|
||||
} else {
|
||||
quote! { [u64; 2] }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,10 @@ pub fn gen_debug_impl(
|
|||
format_string.push_str(" }}");
|
||||
tokens.insert(0, quote! { #format_string });
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
||||
quote! {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
fn fmt(&self, f: &mut ::#prefix::fmt::Formatter<'_>) -> ::#prefix ::fmt::Result {
|
||||
write!(f, #( #tokens ),*)
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +156,6 @@ impl<'a> ImplDebug<'a> for Item {
|
|||
TypeKind::Function(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
|
@ -184,32 +185,49 @@ impl<'a> ImplDebug<'a> for Item {
|
|||
// The simple case
|
||||
debug_print(name, quote! { #name_ident })
|
||||
} else {
|
||||
// Let's implement our own print function
|
||||
Some((
|
||||
format!("{}: [{{}}]", name),
|
||||
vec![quote! {
|
||||
self.#name_ident
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
|
||||
.collect::<String>()
|
||||
}],
|
||||
))
|
||||
if ctx.options().use_core {
|
||||
// There is no String in core; reducing field visibility to avoid breaking
|
||||
// no_std setups.
|
||||
Some((
|
||||
format!("{}: [...]", name), vec![]
|
||||
))
|
||||
} else {
|
||||
// Let's implement our own print function
|
||||
Some((
|
||||
format!("{}: [{{}}]", name),
|
||||
vec![quote! {
|
||||
self.#name_ident
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
|
||||
.collect::<String>()
|
||||
}],
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Vector(_, len) => {
|
||||
let self_ids = 0..len;
|
||||
Some((
|
||||
format!("{}({{}})", name),
|
||||
vec![quote! {
|
||||
#(format!("{:?}", self.#self_ids)),*
|
||||
}]
|
||||
))
|
||||
if ctx.options().use_core {
|
||||
// There is no format! in core; reducing field visibility to avoid breaking
|
||||
// no_std setups.
|
||||
Some((
|
||||
format!("{}(...)", name), vec![]
|
||||
))
|
||||
} else {
|
||||
let self_ids = 0..len;
|
||||
Some((
|
||||
format!("{}({{}})", name),
|
||||
vec![quote! {
|
||||
#(format!("{:?}", self.#self_ids)),*
|
||||
}]
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
// We follow the aliases
|
||||
ctx.resolve_item(t).impl_debug(ctx, name)
|
||||
}
|
||||
|
@ -218,7 +236,7 @@ impl<'a> ImplDebug<'a> for Item {
|
|||
let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
|
||||
match *inner_type.kind() {
|
||||
TypeKind::Function(ref sig)
|
||||
if !sig.can_trivially_derive_debug() => {
|
||||
if !sig.can_trivially_derive_debug(ctx) => {
|
||||
Some((format!("{}: FunctionPointer", name), vec![]))
|
||||
}
|
||||
_ => debug_print(name, quote! { #name_ident }),
|
||||
|
|
|
@ -88,7 +88,6 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
|
@ -125,7 +124,8 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
let inner_item = ctx.resolve_item(t);
|
||||
gen_field(ctx, inner_item, name)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ pub mod struct_layout;
|
|||
#[cfg(test)]
|
||||
#[allow(warnings)]
|
||||
pub(crate) mod bitfield_unit;
|
||||
#[cfg(test)]
|
||||
#[cfg(all(test, target_endian = "little"))]
|
||||
mod bitfield_unit_tests;
|
||||
|
||||
use self::helpers::attributes;
|
||||
|
@ -103,6 +103,9 @@ struct CodegenResult<'a> {
|
|||
/// Whether Objective C types have been seen at least once.
|
||||
saw_objc: bool,
|
||||
|
||||
/// Whether Apple block types have been seen at least once.
|
||||
saw_block: bool,
|
||||
|
||||
/// Whether a bitfield allocation unit has been seen at least once.
|
||||
saw_bitfield_unit: bool,
|
||||
|
||||
|
@ -140,6 +143,7 @@ impl<'a> CodegenResult<'a> {
|
|||
saw_bindgen_union: false,
|
||||
saw_incomplete_array: false,
|
||||
saw_objc: false,
|
||||
saw_block: false,
|
||||
saw_bitfield_unit: false,
|
||||
codegen_id: codegen_id,
|
||||
items_seen: Default::default(),
|
||||
|
@ -166,6 +170,10 @@ impl<'a> CodegenResult<'a> {
|
|||
self.saw_objc = true;
|
||||
}
|
||||
|
||||
fn saw_block(&mut self) {
|
||||
self.saw_block = true;
|
||||
}
|
||||
|
||||
fn saw_bitfield_unit(&mut self) {
|
||||
self.saw_bitfield_unit = true;
|
||||
}
|
||||
|
@ -215,6 +223,7 @@ impl<'a> CodegenResult<'a> {
|
|||
self.saw_union |= new.saw_union;
|
||||
self.saw_incomplete_array |= new.saw_incomplete_array;
|
||||
self.saw_objc |= new.saw_objc;
|
||||
self.saw_block |= new.saw_block;
|
||||
self.saw_bitfield_unit |= new.saw_bitfield_unit;
|
||||
|
||||
new.items
|
||||
|
@ -293,7 +302,6 @@ impl AppendImplicitTemplateParams for quote::Tokens {
|
|||
TypeKind::Opaque |
|
||||
TypeKind::Function(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::ObjCSel |
|
||||
TypeKind::TemplateInstantiation(..) => return,
|
||||
|
@ -394,6 +402,9 @@ impl CodeGenerator for Module {
|
|||
}
|
||||
|
||||
if item.id() == ctx.root_module() {
|
||||
if result.saw_block {
|
||||
utils::prepend_block_header(ctx, &mut *result);
|
||||
}
|
||||
if result.saw_bindgen_union {
|
||||
utils::prepend_union_types(ctx, &mut *result);
|
||||
}
|
||||
|
@ -564,10 +575,16 @@ impl CodeGenerator for Var {
|
|||
attrs.push(attributes::link_name(self.name()));
|
||||
}
|
||||
|
||||
let maybe_mut = if self.is_const() {
|
||||
quote! { }
|
||||
} else {
|
||||
quote! { mut }
|
||||
};
|
||||
|
||||
let mut tokens = quote!(
|
||||
extern "C" {
|
||||
#(#attrs)*
|
||||
pub static mut #canonical_ident: #ty;
|
||||
pub static #maybe_mut #canonical_ident: #ty;
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -597,7 +614,6 @@ impl CodeGenerator for Type {
|
|||
TypeKind::Array(..) |
|
||||
TypeKind::Vector(..) |
|
||||
TypeKind::Pointer(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::Function(..) |
|
||||
TypeKind::ResolvedTypeRef(..) |
|
||||
|
@ -610,6 +626,39 @@ impl CodeGenerator for Type {
|
|||
TypeKind::TemplateInstantiation(ref inst) => {
|
||||
inst.codegen(ctx, result, item)
|
||||
}
|
||||
TypeKind::BlockPointer(inner) => {
|
||||
if !ctx.options().generate_block {
|
||||
return;
|
||||
}
|
||||
|
||||
let inner_item = inner.into_resolver()
|
||||
.through_type_refs()
|
||||
.resolve(ctx);
|
||||
let name = item.canonical_name(ctx);
|
||||
|
||||
let inner_rust_type = {
|
||||
if let TypeKind::Function(fnsig) = inner_item.kind().expect_type().kind() {
|
||||
utils::fnsig_block(ctx, fnsig)
|
||||
} else {
|
||||
panic!("invalid block typedef: {:?}", inner_item)
|
||||
}
|
||||
};
|
||||
|
||||
let rust_name = ctx.rust_ident(&name);
|
||||
|
||||
let mut tokens = if let Some(comment) = item.comment(ctx) {
|
||||
attributes::doc(comment)
|
||||
} else {
|
||||
quote! {}
|
||||
};
|
||||
|
||||
tokens.append_all(quote! {
|
||||
pub type #rust_name = #inner_rust_type ;
|
||||
});
|
||||
|
||||
result.push(tokens);
|
||||
result.saw_block();
|
||||
}
|
||||
TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
|
||||
TypeKind::TemplateAlias(inner, _) |
|
||||
TypeKind::Alias(inner) => {
|
||||
|
@ -1146,7 +1195,7 @@ impl Bitfield {
|
|||
let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
|
||||
"Bitfield without layout? Gah!",
|
||||
);
|
||||
let bitfield_int_ty = helpers::blob(bitfield_ty_layout);
|
||||
let bitfield_int_ty = helpers::blob(ctx, bitfield_ty_layout);
|
||||
|
||||
let offset = self.offset_into_unit();
|
||||
let width = self.width() as u8;
|
||||
|
@ -1328,7 +1377,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
|
|||
let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
|
||||
"Bitfield without layout? Gah!",
|
||||
);
|
||||
let bitfield_int_ty = match helpers::integer_type(bitfield_ty_layout) {
|
||||
let bitfield_int_ty = match helpers::integer_type(ctx, bitfield_ty_layout) {
|
||||
Some(int_ty) => {
|
||||
*bitfield_representable_as_int = true;
|
||||
int_ty
|
||||
|
@ -1501,27 +1550,6 @@ impl CodeGenerator for CompInfo {
|
|||
|
||||
let is_union = self.kind() == CompKind::Union;
|
||||
let layout = item.kind().expect_type().layout(ctx);
|
||||
if is_union && !is_opaque && !self.is_forward_declaration() {
|
||||
result.saw_union();
|
||||
if !self.can_be_rust_union(ctx) {
|
||||
result.saw_bindgen_union();
|
||||
}
|
||||
|
||||
let layout = layout.expect("Unable to get layout information?");
|
||||
let ty = helpers::blob(layout);
|
||||
|
||||
fields.push(if self.can_be_rust_union(ctx) {
|
||||
quote! {
|
||||
_bindgen_union_align: #ty ,
|
||||
}
|
||||
} else {
|
||||
struct_layout.saw_union(layout);
|
||||
|
||||
quote! {
|
||||
pub bindgen_union_field: #ty ,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let mut explicit_align = None;
|
||||
if is_opaque {
|
||||
|
@ -1533,7 +1561,7 @@ impl CodeGenerator for CompInfo {
|
|||
Some(l) => {
|
||||
explicit_align = Some(l.align);
|
||||
|
||||
let ty = helpers::blob(l);
|
||||
let ty = helpers::blob(ctx, l);
|
||||
fields.push(quote! {
|
||||
pub _bindgen_opaque_blob: #ty ,
|
||||
});
|
||||
|
@ -1556,7 +1584,7 @@ impl CodeGenerator for CompInfo {
|
|||
} else {
|
||||
explicit_align = Some(layout.align);
|
||||
if !ctx.options().rust_features.repr_align {
|
||||
let ty = helpers::blob(Layout::new(0, layout.align));
|
||||
let ty = helpers::blob(ctx, Layout::new(0, layout.align));
|
||||
fields.push(quote! {
|
||||
pub __bindgen_align: #ty ,
|
||||
});
|
||||
|
@ -1564,6 +1592,32 @@ impl CodeGenerator for CompInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if is_union && !self.is_forward_declaration() {
|
||||
result.saw_union();
|
||||
if !self.can_be_rust_union(ctx) {
|
||||
result.saw_bindgen_union();
|
||||
}
|
||||
|
||||
// TODO(emilio): It'd be nice to unify this with the struct path
|
||||
// above somehow.
|
||||
let layout = layout.expect("Unable to get layout information?");
|
||||
|
||||
if struct_layout.requires_explicit_align(layout) {
|
||||
explicit_align = Some(layout.align);
|
||||
}
|
||||
|
||||
let ty = helpers::blob(ctx, layout);
|
||||
fields.push(if self.can_be_rust_union(ctx) {
|
||||
quote! {
|
||||
_bindgen_union_align: #ty ,
|
||||
}
|
||||
} else {
|
||||
struct_layout.saw_union(layout);
|
||||
|
||||
quote! {
|
||||
pub bindgen_union_field: #ty ,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// C++ requires every struct to be addressable, so what C++ compilers do
|
||||
|
@ -1590,7 +1644,7 @@ impl CodeGenerator for CompInfo {
|
|||
};
|
||||
|
||||
if has_address {
|
||||
let ty = helpers::blob(Layout::new(1, 1));
|
||||
let ty = helpers::blob(ctx, Layout::new(1, 1));
|
||||
fields.push(quote! {
|
||||
pub _address: #ty,
|
||||
});
|
||||
|
@ -1747,7 +1801,7 @@ impl CodeGenerator for CompInfo {
|
|||
// all the tests to shit when parsing things like max_align_t.
|
||||
if self.found_unknown_attr() {
|
||||
warn!(
|
||||
"Type {} has an unkown attribute that may affect layout",
|
||||
"Type {} has an unknown attribute that may affect layout",
|
||||
canonical_ident.as_str()
|
||||
);
|
||||
}
|
||||
|
@ -1920,8 +1974,10 @@ impl CodeGenerator for CompInfo {
|
|||
self.kind(),
|
||||
);
|
||||
|
||||
let prefix = ctx.trait_prefix();
|
||||
|
||||
result.push(quote! {
|
||||
impl #generics ::std::fmt::Debug for #ty_for_impl {
|
||||
impl #generics ::#prefix::fmt::Debug for #ty_for_impl {
|
||||
#impl_
|
||||
}
|
||||
});
|
||||
|
@ -2516,22 +2572,10 @@ impl CodeGenerator for Enum {
|
|||
}
|
||||
};
|
||||
|
||||
// ModuleConsts has higher precedence before Rust in order to avoid problems with
|
||||
// overlapping match patterns
|
||||
let variation = if self.is_constified_enum_module(ctx, item) {
|
||||
EnumVariation::ModuleConsts
|
||||
} else if self.is_bitfield(ctx, item) {
|
||||
EnumVariation::Bitfield
|
||||
} else if self.is_rustified_enum(ctx, item) {
|
||||
EnumVariation::Rust
|
||||
} else if self.is_constified_enum(ctx, item) {
|
||||
EnumVariation::Consts
|
||||
} else {
|
||||
ctx.options().default_enum_style
|
||||
};
|
||||
|
||||
let mut attrs = vec![];
|
||||
|
||||
let variation = self.computed_enum_variation(ctx, item);
|
||||
|
||||
// TODO(emilio): Delegate this to the builders?
|
||||
if variation.is_rust() {
|
||||
attrs.push(attributes::repr(repr_name));
|
||||
|
@ -2544,9 +2588,17 @@ impl CodeGenerator for Enum {
|
|||
}
|
||||
|
||||
if !variation.is_const() {
|
||||
attrs.push(attributes::derives(
|
||||
&["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"],
|
||||
));
|
||||
let mut derives = vec!["Debug", "Copy", "Clone", "PartialEq", "Eq", "Hash"];
|
||||
|
||||
if item.can_derive_partialord(ctx) {
|
||||
derives.push("PartialOrd");
|
||||
}
|
||||
|
||||
if item.can_derive_ord(ctx) {
|
||||
derives.push("Ord");
|
||||
}
|
||||
|
||||
attrs.push(attributes::derives(&derives));
|
||||
}
|
||||
|
||||
fn add_constant<'a>(
|
||||
|
@ -2759,7 +2811,7 @@ trait TryToOpaque {
|
|||
extra: &Self::Extra,
|
||||
) -> error::Result<quote::Tokens> {
|
||||
self.try_get_layout(ctx, extra).map(|layout| {
|
||||
helpers::blob(layout)
|
||||
helpers::blob(ctx, layout)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2786,7 +2838,7 @@ trait ToOpaque: TryToOpaque {
|
|||
extra: &Self::Extra,
|
||||
) -> quote::Tokens {
|
||||
let layout = self.get_layout(ctx, extra);
|
||||
helpers::blob(layout)
|
||||
helpers::blob(ctx, layout)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2844,7 +2896,7 @@ where
|
|||
|_| if let Ok(layout) =
|
||||
self.try_get_layout(ctx, extra)
|
||||
{
|
||||
Ok(helpers::blob(layout))
|
||||
Ok(helpers::blob(ctx, layout))
|
||||
} else {
|
||||
Err(error::Error::NoLayoutForOpaqueBlob)
|
||||
},
|
||||
|
@ -2996,7 +3048,7 @@ impl TryToRustTy for Type {
|
|||
IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")),
|
||||
IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")),
|
||||
IntKind::WChar { size } => {
|
||||
let ty = Layout::known_type_for_size(size)
|
||||
let ty = Layout::known_type_for_size(ctx, size)
|
||||
.expect("Non-representable wchar_t?");
|
||||
let ident = ctx.rust_ident_raw(ty);
|
||||
Ok(quote! { #ident })
|
||||
|
@ -3018,17 +3070,27 @@ impl TryToRustTy for Type {
|
|||
#ident
|
||||
})
|
||||
}
|
||||
// FIXME: This doesn't generate the proper alignment, but we
|
||||
// can't do better right now. We should be able to use
|
||||
// i128/u128 when they're available.
|
||||
IntKind::U128 | IntKind::I128 => {
|
||||
Ok(quote! { [u64; 2] })
|
||||
IntKind::U128 => {
|
||||
Ok(if ctx.options().rust_features.i128_and_u128 {
|
||||
quote! { u128 }
|
||||
} else {
|
||||
// Best effort thing, but wrong alignment
|
||||
// unfortunately.
|
||||
quote! { [u64; 2] }
|
||||
})
|
||||
}
|
||||
IntKind::I128 => {
|
||||
Ok(if ctx.options().rust_features.i128_and_u128 {
|
||||
quote! { i128 }
|
||||
} else {
|
||||
quote! { [u64; 2] }
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)),
|
||||
TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))),
|
||||
TypeKind::Complex(fk) => {
|
||||
let float_path = float_kind_rust_type(ctx, fk);
|
||||
let float_path = float_kind_rust_type(ctx, fk, self.layout(ctx));
|
||||
|
||||
ctx.generated_bindgen_complex();
|
||||
Ok(if ctx.options().enable_cxx_namespaces {
|
||||
|
@ -3069,20 +3131,20 @@ impl TryToRustTy for Type {
|
|||
}
|
||||
TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
|
||||
TypeKind::TemplateAlias(..) |
|
||||
TypeKind::Alias(..) => {
|
||||
TypeKind::Alias(..) |
|
||||
TypeKind::BlockPointer(..) => {
|
||||
if self.is_block_pointer() && !ctx.options().generate_block {
|
||||
let void = raw_type(ctx, "c_void");
|
||||
return Ok(void.to_ptr(/* is_const = */ false));
|
||||
}
|
||||
let template_params = item.used_template_params(ctx)
|
||||
.into_iter()
|
||||
.filter(|param| param.is_template_param(ctx, &()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let spelling = self.name().expect("Unnamed alias?");
|
||||
if item.is_opaque(ctx, &()) && !template_params.is_empty() {
|
||||
self.try_to_opaque(ctx, item)
|
||||
} else if let Some(ty) = utils::type_from_named(
|
||||
ctx,
|
||||
spelling,
|
||||
)
|
||||
{
|
||||
} else if let Some(ty) = self.name().and_then(|name| utils::type_from_named(ctx, name)) {
|
||||
Ok(ty)
|
||||
} else {
|
||||
utils::build_path(item, ctx)
|
||||
|
@ -3099,13 +3161,6 @@ impl TryToRustTy for Type {
|
|||
utils::build_path(item, ctx)
|
||||
}
|
||||
TypeKind::Opaque => self.try_to_opaque(ctx, item),
|
||||
TypeKind::BlockPointer => {
|
||||
let void = raw_type(ctx, "c_void");
|
||||
Ok(void.to_ptr(
|
||||
/* is_const = */
|
||||
false
|
||||
))
|
||||
}
|
||||
TypeKind::Pointer(inner) |
|
||||
TypeKind::Reference(inner) => {
|
||||
let is_const = ctx.resolve_type(inner).is_const();
|
||||
|
@ -3558,6 +3613,25 @@ mod utils {
|
|||
result.extend(old_items.into_iter());
|
||||
}
|
||||
|
||||
pub fn prepend_block_header(
|
||||
ctx: &BindgenContext,
|
||||
result: &mut Vec<quote::Tokens>,
|
||||
) {
|
||||
let use_block = if ctx.options().block_extern_crate {
|
||||
quote! {
|
||||
extern crate block;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
use block;
|
||||
}
|
||||
};
|
||||
|
||||
let items = vec![use_block];
|
||||
let old_items = mem::replace(result, items);
|
||||
result.extend(old_items.into_iter());
|
||||
}
|
||||
|
||||
pub fn prepend_union_types(
|
||||
ctx: &BindgenContext,
|
||||
result: &mut Vec<quote::Tokens>,
|
||||
|
@ -3614,7 +3688,7 @@ mod utils {
|
|||
|
||||
let union_field_debug_impl = quote! {
|
||||
impl<T> ::#prefix::fmt::Debug for __BindgenUnionField<T> {
|
||||
fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter)
|
||||
fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
|
||||
-> ::#prefix::fmt::Result {
|
||||
fmt.write_str("__BindgenUnionField")
|
||||
}
|
||||
|
@ -3701,7 +3775,7 @@ mod utils {
|
|||
|
||||
let incomplete_array_debug_impl = quote! {
|
||||
impl<T> ::#prefix::fmt::Debug for __IncompleteArrayField<T> {
|
||||
fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter)
|
||||
fn fmt(&self, fmt: &mut ::#prefix::fmt::Formatter<'_>)
|
||||
-> ::#prefix::fmt::Result {
|
||||
fmt.write_str("__IncompleteArrayField")
|
||||
}
|
||||
|
@ -3869,4 +3943,26 @@ mod utils {
|
|||
|
||||
args
|
||||
}
|
||||
|
||||
pub fn fnsig_block(
|
||||
ctx: &BindgenContext,
|
||||
sig: &FunctionSig,
|
||||
) -> quote::Tokens {
|
||||
let args = sig.argument_types().iter().map(|&(_, ty)| {
|
||||
let arg_item = ctx.resolve_item(ty);
|
||||
|
||||
arg_item.to_rust_ty_or_opaque(ctx, &())
|
||||
});
|
||||
|
||||
let return_item = ctx.resolve_item(sig.return_type());
|
||||
let ret_ty = if let TypeKind::Void = *return_item.kind().expect_type().kind() {
|
||||
quote! { () }
|
||||
} else {
|
||||
return_item.to_rust_ty_or_opaque(ctx, &())
|
||||
};
|
||||
|
||||
quote! {
|
||||
*const ::block::Block<(#(#args),*), #ret_ty>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,18 +287,23 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
}
|
||||
|
||||
pub fn requires_explicit_align(&self, layout: Layout) -> bool {
|
||||
let repr_align = self.ctx.options().rust_features().repr_align;
|
||||
|
||||
// Always force explicit repr(align) for stuff more than 16-byte aligned
|
||||
// to work-around https://github.com/rust-lang/rust/issues/54341.
|
||||
//
|
||||
// Worst-case this just generates redundant alignment attributes.
|
||||
if repr_align && self.max_field_align >= 16 {
|
||||
return true;
|
||||
}
|
||||
|
||||
if self.max_field_align >= layout.align {
|
||||
return false;
|
||||
}
|
||||
// At this point we require explicit alignment, but we may not be able
|
||||
// to generate the right bits, let's double check.
|
||||
if self.ctx.options().rust_features().repr_align {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We can only generate up-to a word of alignment unless we support
|
||||
// repr(align).
|
||||
layout.align <= self.ctx.target_pointer_size()
|
||||
repr_align || layout.align <= self.ctx.target_pointer_size()
|
||||
}
|
||||
|
||||
fn padding_bytes(&self, layout: Layout) -> usize {
|
||||
|
@ -306,7 +311,7 @@ impl<'a> StructLayoutTracker<'a> {
|
|||
}
|
||||
|
||||
fn padding_field(&mut self, layout: Layout) -> quote::Tokens {
|
||||
let ty = helpers::blob(layout);
|
||||
let ty = helpers::blob(self.ctx, layout);
|
||||
let padding_count = self.padding_count;
|
||||
|
||||
self.padding_count += 1;
|
||||
|
|
|
@ -96,6 +96,8 @@ macro_rules! rust_target_base {
|
|||
=> Stable_1_21 => 1.21;
|
||||
/// Rust stable 1.25
|
||||
=> Stable_1_25 => 1.25;
|
||||
/// Rust stable 1.26
|
||||
=> Stable_1_26 => 1.26;
|
||||
/// Nightly rust
|
||||
=> Nightly => nightly;
|
||||
);
|
||||
|
@ -172,6 +174,10 @@ rust_feature_def!(
|
|||
/// repr(align) ([PR](https://github.com/rust-lang/rust/pull/47006))
|
||||
=> repr_align;
|
||||
}
|
||||
Stable_1_26 {
|
||||
/// [i128 / u128 support](https://doc.rust-lang.org/std/primitive.i128.html)
|
||||
=> i128_and_u128;
|
||||
}
|
||||
Nightly {
|
||||
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
|
||||
=> thiscall_abi;
|
||||
|
|
|
@ -149,7 +149,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
|
|||
|
||||
if item.is_opaque(self.ctx, &()) {
|
||||
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_copy()
|
||||
l.opaque().can_trivially_derive_copy(self.ctx)
|
||||
});
|
||||
return if layout_can_derive {
|
||||
trace!(" we can trivially derive Copy for the layout");
|
||||
|
@ -173,7 +173,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::Pointer(..) |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
|
@ -204,7 +203,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
let cant_derive_copy = self.is_not_copy(t);
|
||||
if cant_derive_copy {
|
||||
trace!(
|
||||
|
|
|
@ -146,7 +146,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
|
||||
if item.is_opaque(self.ctx, &()) {
|
||||
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_debug()
|
||||
l.opaque().can_trivially_derive_debug(self.ctx)
|
||||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
|
@ -183,7 +183,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::Vector(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
|
@ -213,7 +212,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
if self.is_not_debug(t) {
|
||||
trace!(
|
||||
" aliases and type refs to T which cannot derive \
|
||||
|
@ -242,7 +242,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
}
|
||||
|
||||
if ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_debug()
|
||||
l.opaque().can_trivially_derive_debug(self.ctx)
|
||||
})
|
||||
{
|
||||
trace!(" union layout can trivially derive Debug");
|
||||
|
@ -299,7 +299,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
|
|||
let inner_type =
|
||||
self.ctx.resolve_type(inner).canonical_type(self.ctx);
|
||||
if let TypeKind::Function(ref sig) = *inner_type.kind() {
|
||||
if !sig.can_trivially_derive_debug() {
|
||||
if !sig.can_trivially_derive_debug(self.ctx) {
|
||||
trace!(
|
||||
" function pointer that can't trivially derive Debug"
|
||||
);
|
||||
|
|
|
@ -173,7 +173,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
|
||||
if item.is_opaque(self.ctx, &()) {
|
||||
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_default()
|
||||
l.opaque().can_trivially_derive_default(self.ctx)
|
||||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
|
@ -215,7 +215,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
TypeKind::Reference(..) |
|
||||
TypeKind::NullPtr |
|
||||
TypeKind::Pointer(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::ObjCSel |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
|
@ -244,7 +243,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
if self.is_not_default(t) {
|
||||
trace!(
|
||||
" aliases and type refs to T which cannot derive \
|
||||
|
@ -278,7 +278,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
|
|||
}
|
||||
|
||||
if ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_default()
|
||||
l.opaque().can_trivially_derive_default(self.ctx)
|
||||
})
|
||||
{
|
||||
trace!(" union layout can trivially derive Default");
|
||||
|
|
|
@ -133,7 +133,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
|
||||
if item.is_opaque(self.ctx, &()) {
|
||||
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_hash()
|
||||
l.opaque().can_trivially_derive_hash(self.ctx)
|
||||
});
|
||||
return if layout_can_derive &&
|
||||
!(ty.is_union() &&
|
||||
|
@ -167,7 +167,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
|
@ -219,7 +218,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
let inner_type =
|
||||
self.ctx.resolve_type(inner).canonical_type(self.ctx);
|
||||
if let TypeKind::Function(ref sig) = *inner_type.kind() {
|
||||
if !sig.can_trivially_derive_hash() {
|
||||
if !sig.can_trivially_derive_hash(self.ctx) {
|
||||
trace!(
|
||||
" function pointer that can't trivially derive Hash"
|
||||
);
|
||||
|
@ -231,7 +230,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
}
|
||||
|
||||
TypeKind::Function(ref sig) => {
|
||||
if !sig.can_trivially_derive_hash() {
|
||||
if !sig.can_trivially_derive_hash(self.ctx) {
|
||||
trace!(" function that can't trivially derive Hash");
|
||||
return self.insert(id);
|
||||
}
|
||||
|
@ -241,7 +240,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
if self.cannot_derive_hash.contains(&t.into()) {
|
||||
trace!(
|
||||
" aliases and type refs to T which cannot derive \
|
||||
|
@ -275,7 +275,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
|
|||
}
|
||||
|
||||
if ty.layout(self.ctx).map_or(true, |l| {
|
||||
l.opaque().can_trivially_derive_hash()
|
||||
l.opaque().can_trivially_derive_hash(self.ctx)
|
||||
})
|
||||
{
|
||||
trace!(" union layout can trivially derive Hash");
|
||||
|
|
|
@ -43,7 +43,7 @@ use std::collections::hash_map::Entry;
|
|||
pub struct CannotDerivePartialEqOrPartialOrd<'ctx> {
|
||||
ctx: &'ctx BindgenContext,
|
||||
|
||||
// The incremental result of this analysis's computation.
|
||||
// The incremental result of this analysis's computation.
|
||||
// Contains information whether particular item can derive `PartialEq`/`PartialOrd`.
|
||||
can_derive_partialeq_or_partialord: HashMap<ItemId, CanDerive>,
|
||||
|
||||
|
@ -129,7 +129,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
|
||||
let layout_can_derive = ty.layout(self.ctx)
|
||||
.map_or(CanDerive::Yes, |l| {
|
||||
l.opaque().can_trivially_derive_partialeq_or_partialord()
|
||||
l.opaque().can_trivially_derive_partialeq_or_partialord(self.ctx)
|
||||
});
|
||||
|
||||
match layout_can_derive {
|
||||
|
@ -158,7 +158,6 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::UnresolvedTypeRef(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::ObjCInterface(..) |
|
||||
TypeKind::ObjCId |
|
||||
|
@ -211,7 +210,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
let inner_type =
|
||||
self.ctx.resolve_type(inner).canonical_type(self.ctx);
|
||||
if let TypeKind::Function(ref sig) = *inner_type.kind() {
|
||||
if sig.can_trivially_derive_partialeq_or_partialord()
|
||||
if sig.can_trivially_derive_partialeq_or_partialord(self.ctx)
|
||||
!= CanDerive::Yes
|
||||
{
|
||||
trace!(
|
||||
|
@ -225,7 +224,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
}
|
||||
|
||||
TypeKind::Function(ref sig) => {
|
||||
if sig.can_trivially_derive_partialeq_or_partialord()
|
||||
if sig.can_trivially_derive_partialeq_or_partialord(self.ctx)
|
||||
!= CanDerive::Yes
|
||||
{
|
||||
trace!(
|
||||
|
@ -259,7 +258,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
let layout_can_derive =
|
||||
ty.layout(self.ctx).map_or(CanDerive::Yes, |l| {
|
||||
l.opaque()
|
||||
.can_trivially_derive_partialeq_or_partialord()
|
||||
.can_trivially_derive_partialeq_or_partialord(self.ctx)
|
||||
});
|
||||
match layout_can_derive {
|
||||
CanDerive::Yes => {
|
||||
|
@ -281,6 +280,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
|
|||
TypeKind::ResolvedTypeRef(..) |
|
||||
TypeKind::TemplateAlias(..) |
|
||||
TypeKind::Alias(..) |
|
||||
TypeKind::BlockPointer(..) |
|
||||
TypeKind::TemplateInstantiation(..) => {
|
||||
return self.constrain_join(item);
|
||||
}
|
||||
|
|
|
@ -122,7 +122,6 @@ impl<'ctx> MonotoneFramework for HasFloat<'ctx> {
|
|||
TypeKind::Function(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::Opaque |
|
||||
TypeKind::Pointer(..) |
|
||||
|
@ -159,7 +158,8 @@ impl<'ctx> MonotoneFramework for HasFloat<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
if self.has_float.contains(&t.into()) {
|
||||
trace!(" aliases and type refs to T which have float \
|
||||
also have float");
|
||||
|
|
|
@ -135,7 +135,6 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> {
|
|||
TypeKind::Function(..) |
|
||||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::TypeParam |
|
||||
TypeKind::Opaque |
|
||||
TypeKind::Pointer(..) |
|
||||
|
@ -166,7 +165,8 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> {
|
|||
|
||||
TypeKind::ResolvedTypeRef(t) |
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) => {
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) => {
|
||||
if self.has_type_parameter_in_array.contains(&t.into()) {
|
||||
trace!(
|
||||
" aliases and type refs to T which have array \
|
||||
|
|
|
@ -261,7 +261,6 @@ impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> {
|
|||
TypeKind::Enum(..) |
|
||||
TypeKind::Reference(..) |
|
||||
TypeKind::NullPtr |
|
||||
TypeKind::BlockPointer |
|
||||
TypeKind::ObjCId |
|
||||
TypeKind::ObjCSel |
|
||||
TypeKind::Pointer(..) => {
|
||||
|
@ -276,6 +275,7 @@ impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> {
|
|||
|
||||
TypeKind::TemplateAlias(t, _) |
|
||||
TypeKind::Alias(t) |
|
||||
TypeKind::BlockPointer(t) |
|
||||
TypeKind::ResolvedTypeRef(t) => {
|
||||
trace!(" aliases and type refs forward to their inner type");
|
||||
self.forward(t, id)
|
||||
|
|
|
@ -35,7 +35,6 @@ fn kind(comment: &str) -> Option<Kind> {
|
|||
|
||||
fn make_indent(indent: usize) -> String {
|
||||
const RUST_INDENTATION: usize = 4;
|
||||
|
||||
iter::repeat(' ').take(indent * RUST_INDENTATION).collect()
|
||||
}
|
||||
|
||||
|
@ -49,12 +48,11 @@ fn preprocess_single_lines(comment: &str, indent: usize) -> String {
|
|||
let mut is_first = true;
|
||||
let lines: Vec<_> = comment
|
||||
.lines()
|
||||
.map(|l| l.trim_left_matches('/').trim())
|
||||
.map(|l| l.trim().trim_left_matches('/'))
|
||||
.map(|l| {
|
||||
let indent = if is_first { "" } else { &*indent };
|
||||
is_first = false;
|
||||
let maybe_space = if l.is_empty() { "" } else { " " };
|
||||
format!("{}///{}{}", indent, maybe_space, l)
|
||||
format!("{}///{}", indent, l)
|
||||
})
|
||||
.collect();
|
||||
lines.join("\n")
|
||||
|
@ -63,30 +61,24 @@ fn preprocess_single_lines(comment: &str, indent: usize) -> String {
|
|||
fn preprocess_multi_line(comment: &str, indent: usize) -> String {
|
||||
let comment = comment
|
||||
.trim_left_matches('/')
|
||||
.trim_left_matches('*')
|
||||
.trim_left_matches('!')
|
||||
.trim_right_matches('/')
|
||||
.trim_right_matches('*')
|
||||
.trim();
|
||||
.trim_right_matches('*');
|
||||
|
||||
let indent = make_indent(indent);
|
||||
// Strip any potential `*` characters preceding each line.
|
||||
let mut is_first = true;
|
||||
let mut lines: Vec<_> = comment.lines()
|
||||
.map(|line| line.trim().trim_left_matches('*').trim())
|
||||
.skip_while(|line| line.is_empty()) // Skip the first empty lines.
|
||||
.map(|line| line.trim().trim_left_matches('*').trim_left_matches('!'))
|
||||
.skip_while(|line| line.trim().is_empty()) // Skip the first empty lines.
|
||||
.map(|line| {
|
||||
let indent = if is_first { "" } else { &*indent };
|
||||
is_first = false;
|
||||
let maybe_space = if line.is_empty() { "" } else { " " };
|
||||
format!("{}///{}{}", indent, maybe_space, line)
|
||||
format!("{}///{}", indent, line)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Remove the trailing line corresponding to the `*/`.
|
||||
let last_line_is_empty = lines.last().map_or(false, |l| l.is_empty());
|
||||
|
||||
if last_line_is_empty {
|
||||
if lines.last().map_or(false, |l| l.trim().is_empty() || l.trim() == "///") {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
|
@ -107,6 +99,7 @@ mod test {
|
|||
fn processes_single_lines_correctly() {
|
||||
assert_eq!(preprocess("/// hello", 0), "/// hello");
|
||||
assert_eq!(preprocess("// hello", 0), "/// hello");
|
||||
assert_eq!(preprocess("// hello", 0), "/// hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -118,7 +111,7 @@ mod test {
|
|||
|
||||
assert_eq!(
|
||||
preprocess("/**\nhello\n*world\n*foo\n*/", 0),
|
||||
"/// hello\n/// world\n/// foo"
|
||||
"///hello\n///world\n///foo"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,7 +226,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T> CanDeriveCopy<'a> for T
|
||||
impl<T> CanDeriveCopy for T
|
||||
where
|
||||
T: Copy + Into<ItemId>
|
||||
{
|
||||
|
@ -514,12 +514,19 @@ const HOST_TARGET: &'static str =
|
|||
fn find_effective_target(clang_args: &[String]) -> (String, bool) {
|
||||
use std::env;
|
||||
|
||||
for opt in clang_args {
|
||||
let mut args = clang_args.iter();
|
||||
while let Some(opt) = args.next() {
|
||||
if opt.starts_with("--target=") {
|
||||
let mut split = opt.split('=');
|
||||
split.next();
|
||||
return (split.next().unwrap().to_owned(), true);
|
||||
}
|
||||
|
||||
if opt == "-target" {
|
||||
if let Some(target) = args.next() {
|
||||
return (target.clone(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're running from a build script, try to find the cargo target.
|
||||
|
@ -576,7 +583,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
|
|||
{
|
||||
if let Some(ref ti) = target_info {
|
||||
if effective_target == HOST_TARGET {
|
||||
assert_eq!(ti.pointer_width / 8, mem::size_of::<*mut ()>());
|
||||
assert_eq!(
|
||||
ti.pointer_width / 8, mem::size_of::<*mut ()>(),
|
||||
"{:?} {:?}", effective_target, HOST_TARGET
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -844,57 +854,58 @@ If you encounter an error missing from this list, please file an issue or a PR!"
|
|||
name.contains("$") ||
|
||||
match name {
|
||||
"abstract" |
|
||||
"alignof" |
|
||||
"as" |
|
||||
"become" |
|
||||
"box" |
|
||||
"alignof" |
|
||||
"as" |
|
||||
"async" |
|
||||
"become" |
|
||||
"box" |
|
||||
"break" |
|
||||
"const" |
|
||||
"continue" |
|
||||
"crate" |
|
||||
"do" |
|
||||
"const" |
|
||||
"continue" |
|
||||
"crate" |
|
||||
"do" |
|
||||
"else" |
|
||||
"enum" |
|
||||
"extern" |
|
||||
"false" |
|
||||
"final" |
|
||||
"enum" |
|
||||
"extern" |
|
||||
"false" |
|
||||
"final" |
|
||||
"fn" |
|
||||
"for" |
|
||||
"if" |
|
||||
"impl" |
|
||||
"in" |
|
||||
"for" |
|
||||
"if" |
|
||||
"impl" |
|
||||
"in" |
|
||||
"let" |
|
||||
"loop" |
|
||||
"macro" |
|
||||
"match" |
|
||||
"mod" |
|
||||
"loop" |
|
||||
"macro" |
|
||||
"match" |
|
||||
"mod" |
|
||||
"move" |
|
||||
"mut" |
|
||||
"offsetof" |
|
||||
"override" |
|
||||
"priv" |
|
||||
"mut" |
|
||||
"offsetof" |
|
||||
"override" |
|
||||
"priv" |
|
||||
"proc" |
|
||||
"pub" |
|
||||
"pure" |
|
||||
"ref" |
|
||||
"return" |
|
||||
"pub" |
|
||||
"pure" |
|
||||
"ref" |
|
||||
"return" |
|
||||
"Self" |
|
||||
"self" |
|
||||
"sizeof" |
|
||||
"static" |
|
||||
"struct" |
|
||||
"self" |
|
||||
"sizeof" |
|
||||
"static" |
|
||||
"struct" |
|
||||
"super" |
|
||||
"trait" |
|
||||
"true" |
|
||||
"type" |
|
||||
"typeof" |
|
||||
"trait" |
|
||||
"true" |
|
||||
"type" |
|
||||
"typeof" |
|
||||
"unsafe" |
|
||||
"unsized" |
|
||||
"use" |
|
||||
"virtual" |
|
||||
"where" |
|
||||
"unsized" |
|
||||
"use" |
|
||||
"virtual" |
|
||||
"where" |
|
||||
"while" |
|
||||
"yield" |
|
||||
"yield" |
|
||||
"bool" |
|
||||
"_" => true,
|
||||
_ => false,
|
||||
|
|
|
@ -30,15 +30,15 @@ pub trait CanDeriveDebug {
|
|||
pub trait CanTriviallyDeriveDebug {
|
||||
/// Return `true` if `Debug` can trivially be derived for this thing,
|
||||
/// `false` otherwise.
|
||||
fn can_trivially_derive_debug(&self) -> bool;
|
||||
fn can_trivially_derive_debug(&self, ctx: &BindgenContext) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that encapsulates the logic for whether or not we can derive `Copy`
|
||||
/// for a given thing.
|
||||
pub trait CanDeriveCopy<'a> {
|
||||
pub trait CanDeriveCopy {
|
||||
/// Return `true` if `Copy` can be derived for this thing, `false`
|
||||
/// otherwise.
|
||||
fn can_derive_copy(&'a self, ctx: &'a BindgenContext) -> bool;
|
||||
fn can_derive_copy(&self, ctx: &BindgenContext) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that encapsulates the logic for whether or not we can trivially
|
||||
|
@ -47,7 +47,7 @@ pub trait CanDeriveCopy<'a> {
|
|||
pub trait CanTriviallyDeriveCopy {
|
||||
/// Return `true` if `Copy` can be trivially derived for this thing, `false`
|
||||
/// otherwise.
|
||||
fn can_trivially_derive_copy(&self) -> bool;
|
||||
fn can_trivially_derive_copy(&self, ctx: &BindgenContext) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that encapsulates the logic for whether or not we can derive
|
||||
|
@ -64,7 +64,7 @@ pub trait CanDeriveDefault {
|
|||
pub trait CanTriviallyDeriveDefault {
|
||||
/// Return `true` if `Default` can trivially derived for this thing, `false`
|
||||
/// otherwise.
|
||||
fn can_trivially_derive_default(&self) -> bool;
|
||||
fn can_trivially_derive_default(&self, ctx: &BindgenContext) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that encapsulates the logic for whether or not we can derive `Hash`
|
||||
|
@ -111,7 +111,7 @@ pub trait CanDeriveOrd {
|
|||
pub trait CanTriviallyDeriveHash {
|
||||
/// Return `true` if `Hash` can trivially be derived for this thing, `false`
|
||||
/// otherwise.
|
||||
fn can_trivially_derive_hash(&self) -> bool;
|
||||
fn can_trivially_derive_hash(&self, ctx: &BindgenContext) -> bool;
|
||||
}
|
||||
|
||||
/// A trait that encapsulates the logic for whether or not we can trivially
|
||||
|
@ -120,11 +120,11 @@ pub trait CanTriviallyDeriveHash {
|
|||
pub trait CanTriviallyDerivePartialEqOrPartialOrd {
|
||||
/// Return `Yes` if `PartialEq` or `PartialOrd` can trivially be derived
|
||||
/// for this thing.
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive;
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self, ctx: &BindgenContext) -> CanDerive;
|
||||
}
|
||||
|
||||
/// Whether it is possible or not to automatically derive trait for an item.
|
||||
///
|
||||
///
|
||||
/// ```ignore
|
||||
/// No
|
||||
/// ^
|
||||
|
@ -134,7 +134,7 @@ pub trait CanTriviallyDerivePartialEqOrPartialOrd {
|
|||
/// |
|
||||
/// Yes
|
||||
/// ```
|
||||
///
|
||||
///
|
||||
/// Initially we assume that we can derive trait for all types and then
|
||||
/// update our understanding as we learn more about each type.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord)]
|
||||
|
@ -144,7 +144,7 @@ pub enum CanDerive {
|
|||
|
||||
/// The only thing that stops us from automatically deriving is that
|
||||
/// array with more than maximum number of elements is used.
|
||||
///
|
||||
///
|
||||
/// This means we probably can "manually" implement such trait.
|
||||
ArrayTooLarge,
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use super::context::{BindgenContext, TypeId};
|
||||
use super::item::Item;
|
||||
use super::super::codegen::EnumVariation;
|
||||
use super::ty::TypeKind;
|
||||
use clang;
|
||||
use ir::annotations::Annotations;
|
||||
|
@ -142,32 +143,33 @@ impl Enum {
|
|||
let path = item.canonical_path(ctx);
|
||||
let enum_ty = item.expect_type();
|
||||
|
||||
let path_matches = enums.matches(&path[1..].join("::"));
|
||||
let enum_is_anon = enum_ty.name().is_none();
|
||||
let a_variant_matches = self.variants().iter().any(|v| {
|
||||
enums.matches(&v.name())
|
||||
});
|
||||
path_matches || (enum_is_anon && a_variant_matches)
|
||||
if enums.matches(&path[1..].join("::")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test the variants if the enum is anonymous.
|
||||
if enum_ty.name().is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.variants().iter().any(|v| enums.matches(&v.name()))
|
||||
}
|
||||
|
||||
/// Whether the enum should be a bitfield
|
||||
pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().bitfield_enums, item)
|
||||
}
|
||||
|
||||
/// Whether the enum should be an constified enum module
|
||||
pub fn is_constified_enum_module(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().constified_enum_modules, item)
|
||||
}
|
||||
|
||||
/// Whether the enum should be an set of constants
|
||||
pub fn is_constified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().constified_enums, item)
|
||||
}
|
||||
|
||||
/// Whether the enum should be a Rust enum
|
||||
pub fn is_rustified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
|
||||
self.is_matching_enum(ctx, &ctx.options().rustified_enums, item)
|
||||
/// Returns the final representation of the enum.
|
||||
pub fn computed_enum_variation(&self, ctx: &BindgenContext, item: &Item) -> EnumVariation {
|
||||
// ModuleConsts has higher precedence before Rust in order to avoid
|
||||
// problems with overlapping match patterns.
|
||||
if self.is_matching_enum(ctx, &ctx.options().constified_enum_modules, item) {
|
||||
EnumVariation::ModuleConsts
|
||||
} else if self.is_matching_enum(ctx, &ctx.options().bitfield_enums, item) {
|
||||
EnumVariation::Bitfield
|
||||
} else if self.is_matching_enum(ctx, &ctx.options().rustified_enums, item) {
|
||||
EnumVariation::Rust
|
||||
} else if self.is_matching_enum(ctx, &ctx.options().constified_enums, item) {
|
||||
EnumVariation::Consts
|
||||
} else {
|
||||
ctx.options().default_enum_style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -442,7 +442,16 @@ impl FunctionSig {
|
|||
ty.ret_type().ok_or(ParseError::Continue)?
|
||||
};
|
||||
let ret = Item::from_ty_or_ref(ty_ret_type, cursor, None, ctx);
|
||||
let call_conv = ty.call_conv();
|
||||
|
||||
// Clang plays with us at "find the calling convention", see #549 and
|
||||
// co. This seems to be a better fix than that commit.
|
||||
let mut call_conv = ty.call_conv();
|
||||
if let Some(ty) = cursor.cur_type().canonical_type().pointee_type() {
|
||||
let cursor_call_conv = ty.call_conv();
|
||||
if cursor_call_conv != CXCallingConv_Invalid {
|
||||
call_conv = cursor_call_conv;
|
||||
}
|
||||
}
|
||||
let abi = get_abi(call_conv);
|
||||
|
||||
if abi.is_unknown() {
|
||||
|
@ -581,26 +590,23 @@ impl Trace for FunctionSig {
|
|||
}
|
||||
|
||||
impl CanTriviallyDeriveDebug for FunctionSig {
|
||||
fn can_trivially_derive_debug(&self) -> bool {
|
||||
fn can_trivially_derive_debug(&self, _: &BindgenContext) -> bool {
|
||||
self.function_pointers_can_derive()
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDeriveHash for FunctionSig {
|
||||
fn can_trivially_derive_hash(&self) -> bool {
|
||||
fn can_trivially_derive_hash(&self, _: &BindgenContext) -> bool {
|
||||
self.function_pointers_can_derive()
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDerivePartialEqOrPartialOrd for FunctionSig {
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive {
|
||||
if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
|
||||
return CanDerive::No;
|
||||
}
|
||||
|
||||
match self.abi {
|
||||
Abi::C | Abi::Unknown(..) => CanDerive::Yes,
|
||||
_ => CanDerive::No,
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self, _: &BindgenContext) -> CanDerive {
|
||||
if self.function_pointers_can_derive() {
|
||||
CanDerive::Yes
|
||||
} else {
|
||||
CanDerive::No
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use super::function::{Function, FunctionKind};
|
|||
use super::item_kind::ItemKind;
|
||||
use super::layout::Opaque;
|
||||
use super::module::Module;
|
||||
use super::super::codegen::CONSTIFIED_ENUM_MODULE_REPR_NAME;
|
||||
use super::super::codegen::{CONSTIFIED_ENUM_MODULE_REPR_NAME, EnumVariation};
|
||||
use super::template::{AsTemplateParam, TemplateParameters};
|
||||
use super::traversal::{EdgeKind, Trace, Tracer};
|
||||
use super::ty::{Type, TypeKind};
|
||||
|
@ -329,7 +329,7 @@ impl CanDeriveDefault for Item {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> CanDeriveCopy<'a> for Item {
|
||||
impl CanDeriveCopy for Item {
|
||||
fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
|
||||
self.id().can_derive_copy(ctx)
|
||||
}
|
||||
|
@ -637,6 +637,7 @@ impl Item {
|
|||
|
||||
let path = self.canonical_path(ctx);
|
||||
let name = path[1..].join("::");
|
||||
ctx.options().blacklisted_items.matches(&name) ||
|
||||
match self.kind {
|
||||
ItemKind::Type(..) => {
|
||||
ctx.options().blacklisted_types.matches(&name) ||
|
||||
|
@ -928,7 +929,7 @@ impl Item {
|
|||
|
||||
match *type_.kind() {
|
||||
TypeKind::Enum(ref enum_) => {
|
||||
enum_.is_constified_enum_module(ctx, self)
|
||||
enum_.computed_enum_variation(ctx, self) == EnumVariation::ModuleConsts
|
||||
}
|
||||
TypeKind::Alias(inner_id) => {
|
||||
// TODO(emilio): Make this "hop through type aliases that aren't
|
||||
|
|
|
@ -36,8 +36,12 @@ fn test_layout_for_size() {
|
|||
|
||||
impl Layout {
|
||||
/// Gets the integer type name for a given known size.
|
||||
pub fn known_type_for_size(size: usize) -> Option<&'static str> {
|
||||
pub fn known_type_for_size(
|
||||
ctx: &BindgenContext,
|
||||
size: usize,
|
||||
) -> Option<&'static str> {
|
||||
Some(match size {
|
||||
16 if ctx.options().rust_features.i128_and_u128 => "u128",
|
||||
8 => "u64",
|
||||
4 => "u32",
|
||||
2 => "u16",
|
||||
|
@ -105,14 +109,14 @@ impl Opaque {
|
|||
|
||||
/// Return the known rust type we should use to create a correctly-aligned
|
||||
/// field with this layout.
|
||||
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
|
||||
Layout::known_type_for_size(self.0.align)
|
||||
pub fn known_rust_type_for_array(&self,ctx: &BindgenContext) -> Option<&'static str> {
|
||||
Layout::known_type_for_size(ctx, self.0.align)
|
||||
}
|
||||
|
||||
/// Return the array size that an opaque type for this layout should have if
|
||||
/// we know the correct type for it, or `None` otherwise.
|
||||
pub fn array_size(&self) -> Option<usize> {
|
||||
if self.known_rust_type_for_array().is_some() {
|
||||
pub fn array_size(&self, ctx: &BindgenContext) -> Option<usize> {
|
||||
if self.known_rust_type_for_array(ctx).is_some() {
|
||||
Some(self.0.size / cmp::max(self.0.align, 1))
|
||||
} else {
|
||||
None
|
||||
|
@ -122,45 +126,45 @@ impl Opaque {
|
|||
/// Return `true` if this opaque layout's array size will fit within the
|
||||
/// maximum number of array elements that Rust allows deriving traits
|
||||
/// with. Return `false` otherwise.
|
||||
pub fn array_size_within_derive_limit(&self) -> bool {
|
||||
self.array_size().map_or(false, |size| {
|
||||
pub fn array_size_within_derive_limit(&self, ctx: &BindgenContext) -> bool {
|
||||
self.array_size(ctx).map_or(false, |size| {
|
||||
size <= RUST_DERIVE_IN_ARRAY_LIMIT
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDeriveDebug for Opaque {
|
||||
fn can_trivially_derive_debug(&self) -> bool {
|
||||
self.array_size_within_derive_limit()
|
||||
fn can_trivially_derive_debug(&self, ctx: &BindgenContext) -> bool {
|
||||
self.array_size_within_derive_limit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDeriveDefault for Opaque {
|
||||
fn can_trivially_derive_default(&self) -> bool {
|
||||
self.array_size_within_derive_limit()
|
||||
fn can_trivially_derive_default(&self, ctx: &BindgenContext) -> bool {
|
||||
self.array_size_within_derive_limit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDeriveCopy for Opaque {
|
||||
fn can_trivially_derive_copy(&self) -> bool {
|
||||
self.array_size_within_derive_limit()
|
||||
fn can_trivially_derive_copy(&self, ctx: &BindgenContext) -> bool {
|
||||
self.array_size_within_derive_limit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDeriveHash for Opaque {
|
||||
fn can_trivially_derive_hash(&self) -> bool {
|
||||
self.array_size_within_derive_limit()
|
||||
fn can_trivially_derive_hash(&self, ctx: &BindgenContext) -> bool {
|
||||
self.array_size_within_derive_limit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque {
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self) -> CanDerive {
|
||||
self.array_size().map_or(CanDerive::No, |size| {
|
||||
if size <= RUST_DERIVE_IN_ARRAY_LIMIT {
|
||||
CanDerive::Yes
|
||||
} else {
|
||||
CanDerive::ArrayTooLarge
|
||||
}
|
||||
})
|
||||
fn can_trivially_derive_partialeq_or_partialord(&self, ctx: &BindgenContext) -> CanDerive {
|
||||
// TODO(emilio): This is inconsistent with the rest of the
|
||||
// CanTriviallyDerive* traits.
|
||||
if self.array_size_within_derive_limit(ctx) {
|
||||
CanDerive::Yes
|
||||
} else {
|
||||
CanDerive::ArrayTooLarge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче