Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .sources/VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@
# appear in docs before they ship to users.
# -------------------------------------------------------

motoko v1.16.1 01aee06
motoko v2.2.1 5e6790e
internetidentity release-2026-10-16 8d3e876b
2 changes: 1 addition & 1 deletion .sources/motoko
Submodule motoko updated 1780 files
21 changes: 10 additions & 11 deletions docs/languages/motoko/base-core-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ The following modules have been **removed** in the core package:

- `AssocList` - Use `Map` or `pure/Map` instead
- `Buffer` - Use `List` or `VarArray` instead
- `ExperimentalStableMemory` - Deprecated
- `Hash` - Vulnerable to hash collision attacks
- `HashMap` - Use `Map` or `pure/Map`
- `Heap` - Use `Map` or `Set` instead
Expand Down Expand Up @@ -216,12 +215,12 @@ import Debug "mo:base/Debug";

persistent actor {
// Iterate through -3, -2, -1, 0, 1, 2 (exclusive upper bound)
for (number in Int.range(-3, 3)) {
for number in Int.range(-3, 3) {
Debug.print(debug_show number);
};

// Iterate through -3, -2, -1, 0, 1, 2, 3
for (number in Int.rangeInclusive(-3, 3)) {
for number in Int.rangeInclusive(-3, 3) {
Debug.print(debug_show number);
};
}
Expand Down Expand Up @@ -481,12 +480,12 @@ persistent actor{
};

public func take() : async ?Item {
switch (Deque.popFront(deque)) {
case (?(item, newDeque)) {
switch Deque.popFront(deque) {
case ?(item, newDeque) {
deque := newDeque;
?item;
};
case null { null };
}
case null { null }
};
};
};
Expand All @@ -508,14 +507,14 @@ import Queue "mo:core/Queue";
} {
let queue = Queue.empty<App.Item>();
label l loop {
switch (Deque.popFront(state.deque)) {
case (?(item, deque)) {
switch Deque.popFront(state.deque) {
case ?(item, deque) {
Queue.pushBack(queue, item);
state.deque := deque;
};
}
case null {
break l;
};
}
};
};
{ queue };
Expand Down
18 changes: 9 additions & 9 deletions docs/languages/motoko/fundamentals/actors/actors-async.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,20 +223,20 @@ Customers place orders at a pizza restaurant, but the chef can only make one piz
import Array "mo:core/Array";
import Text "mo:core/Text";

persistent actor PizzaParlor {
actor PizzaParlor {
var orders : [Text] = [];

public shared func placeOrder(order : Text) : async Text {
// Use Array.tabulate to create a new array with the additional element
let newOrders = Array.tabulate<Text>(orders.size() + 1, func(i) {
if (i < orders.size()) { orders[i] } else { order }
if i < orders.size() { orders[i] } else { order }
});
orders := newOrders;
return "Order received: " # order;
};

public shared func makePizza() : async Text {
if (orders.size() == 0) {
if orders.size() == 0 {
return "No orders to make.";
};

Expand Down Expand Up @@ -289,12 +289,12 @@ Use `async*` and `await*` carefully. In Motoko, a regular `await` is a commit po
### Example

```motoko no-repl
persistent actor class (Logger : actor { log : Text -> async () }) {
actor class (Logger : actor { log : Text -> async () }) {

var logging = true;

func maybeLog(msg : Text) : async* () {
if (logging) { await Logger.log(msg) };
if logging { await Logger.log(msg) };
};

func doStuff() : async () {
Expand Down Expand Up @@ -323,7 +323,7 @@ public shared func placeOrder(order : Text) : async Text {
let newOrders = Array.tabulate<Text>(
orders.size() + 1,
func(i) {
if (i < orders.size()) {orders[i]} else {order}
if i < orders.size() {orders[i]} else {order}
}
);

Expand All @@ -343,7 +343,7 @@ A `catch` block can be inserted inside a `try/finally` expression to catch an er
```motoko no-repl
try {
// Code that might throw an error
} catch (e) {
} catch e {
// Handle the error
} finally {
// Cleanup code that always runs
Expand All @@ -357,7 +357,7 @@ When `catch` is used, the `finally` clause is optional. The `catch` block only c
```motoko no-repl
try {
throw Error.reject("Intentional error");
} catch (e) {
} catch e {
// This will catch the explicitly thrown error
}
```
Expand All @@ -367,7 +367,7 @@ When `catch` is used, the `finally` clause is optional. The `catch` block only c
```motoko no-repl
try {
let result = await someAsyncFunction(); // If this returns an error
} catch (e) {
} catch e {
// The error will be caught here
}
```
Expand Down
43 changes: 19 additions & 24 deletions docs/languages/motoko/fundamentals/actors/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ When upgrading a canister, it is important to verify that the upgrade can procee
- Breaking clients due to a Candid interface change.

`dfx` checks these properties statically before attempting the upgrade.
Moreover, with [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko rejects incompatible changes of stable declarations.
Moreover, thanks to [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko rejects incompatible changes of stable declarations.

## Upgrade example

Expand All @@ -21,8 +21,8 @@ The following is a simple example of how to declare a stateful counter:
```

Importantly, in this example, when the counter is upgraded, its state is preserved and the counter will resume from its last value before the upgrade.
This is because actor variables are by default `stable`, meaning their state is persisted across upgrades.
The above actor is equivalent to using an explicit `stable` declaration:
This is because actor variables are persisted across upgrades, by default.
The above actor declaration shows the field without an explicit qualifier, which is the same as writing nothing at all: persistence is the default.

```motoko no-repl file=<motokoExamples>/count-v1stable.mo
```
Expand Down Expand Up @@ -120,7 +120,7 @@ This version is neither compatible to stable type declarations, nor to the Candi
- The change in the return type of `read` is also not safe.
If the change were accepted, then existing clients of the `read` method, that still expect to receive integers, would suddenly start receiving incompatible floats.

With [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko actively rejects any upgrades that require type-incompatible state changes.
Thanks to [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), Motoko actively rejects any upgrades that require type-incompatible state changes.

This is to guarantee that the stable state is always kept safe.

Expand All @@ -133,9 +133,7 @@ In addition to Motoko's runtime check, `dfx` raises a warning message for these
Motoko tolerates Candid interface changes, since these are more likely to be intentional, breaking changes.

:::danger
Versions of Motoko using [classical orthogonal persistence](./orthogonal-persistence/classical.md) will drop the state and reinitialize the counter with `0.0`, if the `dfx` warning is ignored.

For this reason, users should always heed any compatibility warnings issued by `dfx`.
Users should always heed any compatibility warnings issued by `dfx`.
:::


Expand Down Expand Up @@ -179,16 +177,18 @@ The code for the migration function is self-contained and can be placed in its o

The migration function takes a record of stable fields as input and produces a record of stable fields as output.

The input fields extend or override the types of any stable fields in the actor's
stable signature.
The output fields must be declared in the actor's stable signature, and have types that can be consumed by the corresponding declaration in the stable signature.

* All values for the input fields must
be present and of compatible type in the old actor, otherwise the
upgrade traps and rolls back.
* The fields output by the migration
function determine the values of the corresponding stable variables in the
new actor.
* Each input field names a stable variable of the old actor. Its value must be
present and of compatible type in the old actor, otherwise the upgrade traps and
rolls back. The input type is checked against the old actor only: the new actor
may declare the variable with a different type, or not at all.
* An input field is consumed: its old value is not transferred to the new actor.
* Each output field must be declared in the new actor, with a type that can be
consumed by that declaration. The output value becomes the variable's value in
the new actor.
* A consumed field that the new actor declares but the migration function does
not produce is initialized by running its initialization expression, like a
newly declared field (warning M0206). A consumed field that is neither produced
nor declared is dropped (warning M0207).
* All other stable variables of the actor, i.e. those neither consumed nor
produced by the migration function are initialized in the usual way,
either by transfer from the upgraded actor, if declared in that actor, or, if newly declared,
Expand Down Expand Up @@ -367,11 +367,7 @@ cannot be consumed at new type
var Float
```

With [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back.

:::danger
With [classical orthogonal persistence](./orthogonal-persistence/classical.md), however, an upgrade attempt from `v2.wasm` to `v3.wasm` is unpredictable and may lead to partial or complete data loss if the `dfx` warning is ignored.
:::
Thanks to [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back.

## Adding record fields

Expand Down Expand Up @@ -402,8 +398,7 @@ cannot be consumed at new type

Do you want to proceed? yes/No
```
It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](./orthogonal-persistence/classical.md).
Upgrading with [enhanced orthogonal persistence](./orthogonal-persistence/enhanced.md) will trap and roll back, keeping the old state.
It is recommended not to continue: the upgrade will trap and roll back, keeping the old state.

Adding a new record field to the type of existing stable variable is not supported. The reason is simple: the upgrade would need to supply values for the new field out of thin air. In this example, the upgrade would need to conjure up some value for the `description` field of every existing `card` in `map`. Moreover, allowing adding optional fields is also a problem, as a record can be shared from various variables with different static types, some of them already declaring the added field or adding a same-named optional field with a potentially different type (and/or different semantics).

Expand Down
Loading
Loading