-
-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathFrontendObject.wl
More file actions
122 lines (83 loc) · 4 KB
/
FrontendObject.wl
File metadata and controls
122 lines (83 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
BeginPackage["CoffeeLiqueur`Extensions`FrontendObject`"]
(* we have to expose them to System, otherwise Boxes won't work from Mathematica's packages *)
System`CreateFrontEndObject;
System`FrontEndRef;
System`FrontEndExecutable;
System`FrontEndVirtual;
CreateFrontEndObject::usage = "CreateFrontEndObject[expr_, uid_, opts] to force an expression to be evaluated on the frontend inside the container. There are two copies (on Kernel, on Frontend) can be specified using \"Store\"->\"Kernel\", \"Frontend\" or All (by default)"
FrontEndRef::usage = "A readable representation of a stored expression on the kernel"
FrontEndExecutable::usage = "A representation of a stored expression on the frontend"
FrontEndVirtual::usage = ""
Begin["`Internal`"]
$MissingHandler[_, _] := $Failed
(* predefine for the future *)
System`WLXForm;
Objects = <||>
Symbols = <||>
(* ::: Compression for large frontend objects :::*)
Compressed[string_String, {"ExpressionJSON", "ZLIB"}] := ImportByteArray[ByteArray[Developer`RawUncompress[BaseDecode[string]//Normal]], "ExpressionJSON"] // ReleaseHold
compression;
(* [NOTE] This is a deferred compression method, i.e. it is only applied when the object is requested via net / link *)
(* Otherwise ExpressionJSON uncontrollably lifts the context from symbols depending where forntend object was created, *)
(* this leads to some symbols to be falsly assumed to be in Global`, which will throw errors on the frontend *)
(* The only way to avoid this is to deffer compression and ExpressionJSON convertion. *)
(* [FIXME] for the future: switch to Compress and WXF formats instead of JSON !!! *)
(* apply only on large objects*)
compression[expr_, {"ExpressionJSON", "ZLIB", "Defer"}] := Hold[expr] /; (ByteCount[expr] < 0.1 * 1024 * 1024);
SetAttributes[releaseCompression, HoldAll]
releaseCompression[compression[expr_, {"ExpressionJSON", "ZLIB", "Defer"}]] := With[{arr = Normal[ExportByteArray[expr, "ExpressionJSON"] ]},
With[{data = BaseEncode[ByteArray[Developer`RawCompress[arr] ] ]},
Compressed[data, {"ExpressionJSON", "ZLIB"}] // Hold
]
]
releaseCompression[expr_] := expr
CreateFrontEndObject[expr_, uid_String, OptionsPattern[] ] := With[{},
With[{
data = Switch[OptionValue["Store"]
, "Kernel"
, <|"Private" -> compression[expr, {"ExpressionJSON", "ZLIB", "Defer"}]|>
, "Frontend"
, <|"Public" -> compression[expr, {"ExpressionJSON", "ZLIB", "Defer"}]|>
,_
, <|"Private" -> compression[expr, {"ExpressionJSON", "ZLIB", "Defer"}], "Public" :> Objects[uid, "Private"]|>
]
},
If[!AssociationQ[Objects],
Echo["Frontend Objects >> FATAL Error >> Objects are no longer an association"];
Echo["Rebuilding..."];
Objects = <||>;
];
If[KeyExistsQ[Objects, uid],
Objects[uid] = Join[Objects[uid], data ];
,
Objects[uid] = data;
];
];
FrontEndExecutable[uid]
]
CreateFrontEndObject[expr_, opts: OptionsPattern[] ] := CreateFrontEndObject[expr, CreateUUID[], opts]
Options[CreateFrontEndObject] = {"Store" -> All}
FrontEndRef[uid_String] := If[KeyExistsQ[Objects, uid],
With[{o = Objects[uid, "Private"]},
releaseCompression[o] (*Ehhhh Okay... we need to release it anyway *)
] // ReleaseHold
,
$MissingHandler[uid, "Private"] // ReleaseHold
]
FrontEndExecutable /: MakeBoxes[FrontEndExecutable[uid_String], StandardForm] := RowBox[{"(*VB[*)(FrontEndRef[\"", uid, "\"])(*,*)(*", ToString[Compress[Hold[FrontEndExecutable[uid]]], InputForm], "*)(*]VB*)"}]
GetObject[uid_String] := With[{},
(*Echo["Getting object >> "<>uid];*)
If[KeyExistsQ[Objects, uid],
With[{ c = Objects[uid, "Public"] },
releaseCompression[c]
]
,
$Failed
]
]
End[]
Begin["`Tools`"]
UIObjects;
ListObjects[] := Keys[CoffeeLiqueur`Extensions`FrontendObject`Internal`Objects]
End[]
EndPackage[]