Skip to content

Commit cce6674

Browse files
committed
Recover from failure to render mimetype
1 parent 8c145ad commit cce6674

File tree

1 file changed

+57
-50
lines changed

1 file changed

+57
-50
lines changed

notebook/static/notebook/js/outputarea.js

+57-50
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ define([
4848
OutputArea.config_defaults = {
4949
stream_chunk_size: 8192, // chunk size for stream output
5050
};
51-
51+
5252
/**
5353
* Class prototypes
5454
**/
@@ -79,17 +79,17 @@ define([
7979
if (!this.prompt_area) {
8080
this.prompt_overlay.hide();
8181
}
82-
82+
8383
this.wrapper.addClass('output_wrapper');
8484
this.element.addClass('output');
85-
85+
8686
this.collapse_button.addClass("btn btn-default output_collapsed");
8787
this.collapse_button.attr('title', i18n.msg._('click to expand output'));
8888
this.collapse_button.text('. . .');
89-
89+
9090
this.prompt_overlay.addClass('out_prompt_overlay prompt');
9191
this.prompt_overlay.attr('title', i18n.msg._('click to expand output; double click to hide output'));
92-
92+
9393
this.expand();
9494
};
9595

@@ -255,7 +255,7 @@ define([
255255
}
256256
this.append_output(json);
257257
};
258-
258+
259259
// Declare mime type as constants
260260
var MIME_JAVASCRIPT = 'application/javascript';
261261
var MIME_HTML = 'text/html';
@@ -267,8 +267,8 @@ define([
267267
var MIME_GIF = 'image/gif';
268268
var MIME_PDF = 'application/pdf';
269269
var MIME_TEXT = 'text/plain';
270-
271-
270+
271+
272272
OutputArea.output_types = [
273273
MIME_JAVASCRIPT,
274274
MIME_HTML,
@@ -304,10 +304,10 @@ define([
304304
});
305305
return bundle;
306306
};
307-
307+
308308
OutputArea.prototype.append_output = function (json) {
309309
this.expand();
310-
310+
311311
if (this.clear_queued) {
312312
this.clear_output(false);
313313
this._needs_height_reset = true;
@@ -443,7 +443,7 @@ define([
443443
.append($('<div/>').text(err.toString()).addClass('js-error'))
444444
.append($('<div/>').text(i18n.msg._('See your browser Javascript console for more details.')).addClass('js-error'));
445445
};
446-
446+
447447
OutputArea.prototype._safe_append = function (toinsert, toreplace) {
448448
/**
449449
* safely append an item to the document
@@ -657,7 +657,7 @@ define([
657657
element: element,
658658
});
659659
};
660-
660+
661661
OutputArea.prototype.append_display_data = function (json, handle_inserted) {
662662
var toinsert = this.create_output_area();
663663
this._record_display_id(json, toinsert);
@@ -682,36 +682,43 @@ define([
682682
OutputArea.prototype.append_mime_type = function (json, element, handle_inserted) {
683683
for (var i=0; i < OutputArea.display_order.length; i++) {
684684
var type = OutputArea.display_order[i];
685-
var append = OutputArea.append_map[type];
686-
if ((json.data[type] !== undefined) && append) {
687-
var md = json.metadata || {};
688-
var value = json.data[type];
689-
var toinsert;
690-
if (!this.trusted && !OutputArea.safe_outputs[type]) {
691-
// not trusted, sanitize HTML
692-
if (type===MIME_HTML || type==='text/svg') {
693-
var parsed = $(security.sanitize_html_and_parse(value));
694-
toinsert = append.apply(this, [parsed, md, element, handle_inserted]);
685+
686+
try {
687+
var append = OutputArea.append_map[type];
688+
if ((json.data[type] !== undefined) && append) {
689+
var md = json.metadata || {};
690+
var value = json.data[type];
691+
var toinsert;
692+
if (!this.trusted && !OutputArea.safe_outputs[type]) {
693+
// not trusted, sanitize HTML
694+
if (type===MIME_HTML || type==='text/svg') {
695+
var parsed = $(security.sanitize_html_and_parse(value));
696+
toinsert = append.apply(this, [parsed, md, element, handle_inserted]);
697+
} else {
698+
// don't display if we don't know how to sanitize it
699+
console.log("Ignoring untrusted " + type + " output.");
700+
continue;
701+
}
695702
} else {
696-
// don't display if we don't know how to sanitize it
697-
console.log("Ignoring untrusted " + type + " output.");
698-
continue;
703+
toinsert = append.apply(this, [value, md, element, handle_inserted]);
699704
}
700-
} else {
701-
toinsert = append.apply(this, [value, md, element, handle_inserted]);
702-
}
703705

704-
// Since only the png and jpeg mime types call the inserted
705-
// callback, if the mime type is something other we must call the
706-
// inserted callback only when the element is actually inserted
707-
// into the DOM. Use a timeout of 0 to do this.
708-
if ([MIME_PNG, MIME_JPEG, MIME_GIF].indexOf(type) < 0 && handle_inserted !== undefined) {
709-
setTimeout(handle_inserted, 0);
706+
// Since only the png and jpeg mime types call the inserted
707+
// callback, if the mime type is something other we must call the
708+
// inserted callback only when the element is actually inserted
709+
// into the DOM. Use a timeout of 0 to do this.
710+
if ([MIME_PNG, MIME_JPEG, MIME_GIF].indexOf(type) < 0 && handle_inserted !== undefined) {
711+
setTimeout(handle_inserted, 0);
712+
}
713+
this.events.trigger('output_appended.OutputArea', [type, value, md, toinsert]);
714+
return toinsert;
710715
}
711-
this.events.trigger('output_appended.OutputArea', [type, value, md, toinsert]);
712-
return toinsert;
716+
} catch (e) {
717+
console.error('Failed to render mimetype "' + type + '" with: ', e);
718+
continue;
713719
}
714720
}
721+
715722
return null;
716723
};
717724

@@ -783,7 +790,7 @@ define([
783790
var type = MIME_SVG;
784791
var toinsert = this.create_output_subarea(md, "output_svg", type);
785792

786-
// Get the svg element from within the HTML.
793+
// Get the svg element from within the HTML.
787794
// One svg is supposed, but could embed other nested svgs
788795
var svg = $($('<div \>').html(svg_html).find('svg')[0]);
789796
var svg_area = $('<div />');
@@ -819,7 +826,7 @@ define([
819826
}
820827
});
821828
}
822-
829+
823830
var set_width_height = function (img, md, mime) {
824831
/**
825832
* set width and height of an img element from metadata
@@ -832,7 +839,7 @@ define([
832839
img.addClass('unconfined');
833840
}
834841
};
835-
842+
836843
OutputArea.prototype._append_img = function (src_type, md, element, handle_inserted, MIME, type_string) {
837844
var type = MIME;
838845
var toinsert = this.create_output_subarea(md, 'output_' + type_string, type);
@@ -849,15 +856,15 @@ define([
849856
element.append(toinsert);
850857
return toinsert;
851858
};
852-
859+
853860
var append_png = function (png, md, element, handle_inserted) {
854861
return this._append_img(png, md, element, handle_inserted, MIME_PNG, 'png');
855862
};
856863

857864
var append_jpeg = function (jpeg, md, element, handle_inserted) {
858865
return this._append_img(jpeg, md, element, handle_inserted, MIME_JPEG, 'jpeg');
859866
};
860-
867+
861868
var append_gif = function (gif, md, element, handle_inserted) {
862869
return this._append_img(gif, md, element, handle_inserted, MIME_GIF, 'gif');
863870
};
@@ -884,18 +891,18 @@ define([
884891
element.append(toinsert);
885892
return toinsert;
886893
};
887-
894+
888895
OutputArea.prototype.append_raw_input = function (msg) {
889896
var that = this;
890897
this.expand();
891898
var content = msg.content;
892899
var area = this.create_output_area();
893-
900+
894901
// disable any other raw_inputs, if they are left around
895902
$("div.output_subarea.raw_input_container").remove();
896-
903+
897904
var input_type = content.password ? 'password' : 'text';
898-
905+
899906
area.append(
900907
$("<div/>")
901908
.addClass("box-flex1 output_subarea raw_input_container")
@@ -920,7 +927,7 @@ define([
920927
)
921928
.attr("dir","auto")
922929
);
923-
930+
924931
this.element.append(area);
925932
var raw_input = area.find('input.raw_input');
926933
// Register events that enable/disable the keyboard manager while raw
@@ -986,7 +993,7 @@ define([
986993
this.element.height(height);
987994
this.clear_queued = false;
988995
}
989-
996+
990997
// Clear all
991998
// Remove load event handlers from img tags because we don't want
992999
// them to fire if the image is never added to the page.
@@ -997,7 +1004,7 @@ define([
9971004
// Notify others of changes.
9981005
this.element.trigger('changed', {output_area: this});
9991006
this.element.trigger('cleared', {output_area: this});
1000-
1007+
10011008
this.outputs = [];
10021009
this._display_id_targets = {};
10031010
this.trusted = true;
@@ -1104,11 +1111,11 @@ define([
11041111
OutputArea.append_map[MIME_LATEX] = append_latex;
11051112
OutputArea.append_map[MIME_JAVASCRIPT] = append_javascript;
11061113
OutputArea.append_map[MIME_PDF] = append_pdf;
1107-
1114+
11081115
OutputArea.prototype.mime_types = function () {
11091116
return OutputArea.display_order;
11101117
};
1111-
1118+
11121119
OutputArea.prototype.register_mime_type = function (mimetype, append, options) {
11131120
if (mimetype && typeof(append) === 'function') {
11141121
OutputArea.output_types.push(mimetype);

0 commit comments

Comments
 (0)