Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit b7dd1f9

Browse files
committed
Merge pull request #6 from runrev/peter-b/emscripten-standalone
[emscripten] Loading standalones from zip archives
2 parents 2f9f02a + 916e949 commit b7dd1f9

File tree

10 files changed

+387
-11
lines changed

10 files changed

+387
-11
lines changed

engine/emscripten-javascriptify.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ input=$1
1616
output=$2
1717
exports=$3
1818
whitelist=$4
19-
shift 4
19+
preamble=$5
20+
shift 5
2021

2122
for lib in $@ ; do
2223
libs+=\ --js-library\ "${lib}"
@@ -33,6 +34,6 @@ emcc -O2 -g ${CFLAGS} \
3334
-s EMTERPRETIFY_ASYNC=1 \
3435
-s ALLOW_MEMORY_GROWTH=1 \
3536
-s TOTAL_MEMORY=67108864 \
36-
--preload-file boot \
37+
--pre-js "${preamble}" \
3738
${libs}
3839

engine/engine-sources.gypi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,8 +734,12 @@
734734
'src/em-main.cpp',
735735
'src/em-osspec-misc.cpp',
736736
'src/em-osspec-network.cpp',
737+
'src/em-preamble.js',
737738
'src/em-resolution.cpp',
738739
'src/em-stack.cpp',
740+
'src/em-standalone.h',
741+
'src/em-standalone.cpp',
742+
'src/em-standalone.js',
739743
'src/em-surface.h',
740744
'src/em-surface.cpp',
741745
'src/em-system.h',

engine/engine.gyp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,12 +772,13 @@
772772
'<(PRODUCT_DIR)/standalone-community.bc',
773773
'src/em-exported.json',
774774
'src/em-whitelist.json',
775+
'src/em-preamble.js',
775776
'src/em-util.js',
776777
'src/em-async.js',
777778
'src/em-event.js',
778779
'src/em-surface.js',
779780
'src/em-url.js',
780-
'boot',
781+
'src/em-standalone.js',
781782
],
782783

783784
'outputs':
@@ -792,11 +793,13 @@
792793
'<(PRODUCT_DIR)/standalone-community.html',
793794
'src/em-exported.json',
794795
'src/em-whitelist.json',
796+
'src/em-preamble.js',
795797
'src/em-util.js',
796798
'src/em-async.js',
797799
'src/em-event.js',
798800
'src/em-surface.js',
799801
'src/em-url.js',
802+
'src/em-standalone.js',
800803
],
801804
},
802805
],

engine/kernel.gypi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@
9191
[
9292
'../thirdparty/libskia/libskia.gyp:libskia',
9393
],
94+
'sources':
95+
[
96+
'<@(engine_minizip_source_files)',
97+
],
9498
},
9599
],
96100
],

engine/src/em-dc-mainloop.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
1818

1919
#include "em-dc-mainloop.h"
2020
#include "em-dc.h"
21+
#include "em-standalone.h"
2122
#include "em-util.h"
2223

2324
#include "globals.h"
@@ -170,6 +171,16 @@ X_init(int argc,
170171
}
171172
MCEmscriptenCreateArgCountVar(argc);
172173

174+
/* ---------- Initialise the filesystem */
175+
176+
/* We have to unpack the standalone data here rather than in
177+
* MCDispatch::startup() because we have to have font data
178+
* available in the VFS before calling X_open(). */
179+
if (!MCEmscriptenStandaloneUnpack())
180+
{
181+
return false;
182+
}
183+
173184
/* ---------- Continue booting... */
174185
return X_open(argc, argv, envp);
175186
}

engine/src/em-preamble.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/* -*-Javascript-*-
2+
3+
Copyright (C) 2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
// The code in this file is run before the Emscripten engine starts.
20+
21+
// Ensure that there is a Module object.
22+
23+
var Module;
24+
if (!Module) {
25+
Module = (typeof Module !== 'undefined' ? Module : null) || {};
26+
}
27+
28+
// ----------------------------------------------------------------
29+
// Download standalone capsule
30+
// ----------------------------------------------------------------
31+
32+
// Ensure the Module object has a preRun list
33+
if (!Module['preRun']) {
34+
Module['preRun'] = [];
35+
}
36+
37+
// Before the engine is allowed to start, we download the standalone
38+
// capsule, which is a zip file containing the root filesystem to be
39+
// used by the engine.
40+
//
41+
// There are several entries in the Module object that are used when
42+
// downloading the capsule:
43+
//
44+
// * Module['livecodeStandalone'] is the filename of the standalone
45+
// zip file. If it's not provided, the default value is
46+
// 'standalone.zip'.
47+
//
48+
// * Module['locateFile'] is a function that takes a filename and
49+
// returns a corresponding URL.
50+
//
51+
// * Module['livecodeStandalonePrefixURL'] is prepended to the
52+
// standalone filename if there's no locateFile function available.
53+
//
54+
// * Module['livecodeStandaloneRequest'] stores the XMLHttpRequest()
55+
// object used to download the standalone file, for later use.
56+
57+
// FIXME Should this be moved into the engine?
58+
59+
Module['preRun'].push(function() {
60+
61+
// Block running the engine
62+
Module['addRunDependency']('livecodeStandalone');
63+
64+
// Compute the URL from which to download the capsule
65+
var standalone = 'standalone.zip';
66+
67+
if (Module['livecodeStandalone']) {
68+
standalone = Module['livecodeStandalone'];
69+
}
70+
71+
if (typeof Module['locateFile'] === 'function') {
72+
standalone = Module['locateFile'](standalone);
73+
} else if (Module['livecodeStandalonePrefixURL']) {
74+
standalone = Module['livecodeStandalonePrefixURL'] + standalone;
75+
}
76+
77+
// Download the capsule
78+
79+
// FIXME Can we cache the capsule locally?
80+
81+
if (!Module['livecodeStandaloneRequest']) {
82+
var xhr = new XMLHttpRequest();
83+
84+
xhr.addEventListener('load', function(e) {
85+
if (xhr.status !== 200 && xhr.status !== 0) {
86+
throw 'Could not download LiveCode standalone';
87+
}
88+
89+
if (!xhr.response ||
90+
typeof xhr.response !== 'object' ||
91+
!xhr.response.byteLength) {
92+
throw 'Bad result when downloading LiveCode standalone';
93+
}
94+
95+
// Unblock running the engine
96+
Module['removeRunDependency']('livecodeStandalone');
97+
});
98+
99+
xhr.open("GET", standalone);
100+
xhr.responseType = "arraybuffer";
101+
xhr.send();
102+
103+
// Save the request in the Module object for future reference.
104+
Module['livecodeStandaloneRequest'] = xhr;
105+
}
106+
});

engine/src/em-standalone.cpp

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/* -*-c++-*-
2+
3+
Copyright (C) 2003-2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
#include "prefix.h"
20+
21+
#include <foundation.h>
22+
23+
#include "em-standalone.h"
24+
25+
#include "globdefs.h"
26+
#include "parsedef.h"
27+
#include "scriptpt.h"
28+
#include "globals.h"
29+
#include "variable.h"
30+
#include "mcio.h"
31+
#include "osspec.h"
32+
#include "minizip.h"
33+
34+
/* ----------------------------------------------------------------
35+
* Functions implemented in em-standalone.js
36+
* ---------------------------------------------------------------- */
37+
38+
extern "C" int MCEmscriptenStandaloneGetDataJS(void **r_buffer, int *r_length);
39+
40+
/* ---------------------------------------------------------------- */
41+
42+
static bool
43+
__MCEmscriptenStandaloneUnpackWrite(void *context,
44+
const void *p_data,
45+
uint32_t p_data_length,
46+
uint32_t p_data_offset,
47+
uint32_t p_data_total)
48+
{
49+
IO_handle t_handle = static_cast<IO_handle>(context);
50+
const char *t_buffer = static_cast<const char *>(p_data);
51+
52+
/* Write the extracted data */
53+
return (IO_NORMAL == MCS_write(t_buffer + p_data_offset,
54+
p_data_length, 1, t_handle));
55+
}
56+
57+
static bool
58+
__MCEmscriptenStandaloneUnpackExtract(void *context,
59+
MCStringRef p_name)
60+
{
61+
bool t_success = true;
62+
63+
MCLog(" %@", p_name);
64+
65+
MCMiniZipRef t_zip = static_cast<MCMiniZipRef>(context);
66+
67+
/* If the zip file item is a directory, create it */
68+
if (MCStringEndsWithCString(p_name, (const char_t *) "/",
69+
kMCStringOptionCompareExact))
70+
{
71+
t_success = (MCS_mkdir(p_name) ||
72+
MCS_exists(p_name, false));
73+
}
74+
else
75+
{
76+
/* Otherwise, extract it to file */
77+
IO_handle t_handle = NULL;
78+
if (t_success)
79+
{
80+
t_handle = MCS_open(p_name, kMCOpenFileModeWrite, false, false, 0);
81+
t_success = (NULL != t_handle);
82+
}
83+
84+
if (t_success)
85+
{
86+
t_success = MCMiniZipExtractItem(t_zip, p_name,
87+
__MCEmscriptenStandaloneUnpackWrite,
88+
t_handle);
89+
}
90+
91+
if (t_handle != NULL)
92+
{
93+
MCS_close(t_handle);
94+
}
95+
}
96+
97+
return t_success;
98+
}
99+
100+
bool
101+
MCEmscriptenStandaloneUnpack()
102+
{
103+
/* Note that because this function is called before X_open(), it's
104+
* not possible to store diagnostic information in MCresult on
105+
* failure. */
106+
bool t_success = true;
107+
108+
MCLog("Unpacking standalone...");
109+
110+
/* Fetch downloaded standalone data */
111+
void *t_buffer = NULL;
112+
int t_buffer_len = -1;
113+
114+
if (t_success)
115+
{
116+
if (!MCEmscriptenStandaloneGetDataJS(&t_buffer, &t_buffer_len))
117+
{
118+
MCLog("failed to download standalone data");
119+
t_success = false;
120+
}
121+
}
122+
123+
/* Unpack the VFS image to the filesystem root */
124+
MCMiniZipRef t_zip = NULL;
125+
126+
if (t_success)
127+
{
128+
t_success = MCS_setcurdir(MCSTR("/"));
129+
}
130+
131+
if (t_success)
132+
{
133+
MCAssert(0 < t_buffer_len);
134+
MCAssert(NULL != t_buffer);
135+
if (!MCMiniZipOpen(t_buffer, t_buffer_len, t_zip))
136+
{
137+
MCLog("failed to open standalone data as zip archive");
138+
t_success = false;
139+
}
140+
}
141+
142+
if (t_success)
143+
{
144+
if (!MCMiniZipListItems(t_zip,
145+
__MCEmscriptenStandaloneUnpackExtract,
146+
t_zip))
147+
{
148+
MCLog("failed to extract standalone files");
149+
t_success = false;
150+
}
151+
}
152+
153+
/* ---------- 4. Cleanup */
154+
if (NULL != t_zip)
155+
{
156+
MCMiniZipClose(t_zip);
157+
}
158+
if (NULL != t_buffer)
159+
{
160+
free(t_buffer);
161+
}
162+
163+
return t_success;
164+
}

engine/src/em-standalone.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* -*-c++-*-
2+
3+
Copyright (C) 2003-2015 Runtime Revolution Ltd.
4+
5+
This file is part of LiveCode.
6+
7+
LiveCode is free software; you can redistribute it and/or modify it under
8+
the terms of the GNU General Public License v3 as published by the Free
9+
Software Foundation.
10+
11+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
12+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
for more details.
15+
16+
You should have received a copy of the GNU General Public License
17+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
18+
19+
#ifndef __MC_EMSCRIPTEN_STANDALONE_H__
20+
#define __MC_EMSCRIPTEN_STANDALONE_H__
21+
22+
/* Unpack the standalone data into the filesystem. Returns true on
23+
* success. */
24+
bool MCEmscriptenStandaloneUnpack(void);
25+
26+
#endif /* !__MC_EMSCRIPTEN_STANDALONE_H__ */

0 commit comments

Comments
 (0)