/[suikacvs]/messaging/manakai/lib/Message/DOM/Document.pm
Suika

Contents of /messaging/manakai/lib/Message/DOM/Document.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (hide annotations) (download)
Sun Nov 18 11:08:41 2007 UTC (17 years ago) by wakaba
Branch: MAIN
Changes since 1.24: +10 -2 lines
++ manakai/lib/Message/ChangeLog	18 Nov 2007 05:58:46 -0000
2007-11-18  Wakaba  <wakaba@suika.fam.cx>

	* Charset/: New directory.

++ manakai/lib/Message/DOM/ChangeLog	18 Nov 2007 08:56:34 -0000
2007-11-18  Wakaba  <wakaba@suika.fam.cx>

	* Document.pm, Entity.pm (manakai_has_bom,
	manakai_charset): New attributes.

++ manakai/lib/Message/Charset/ChangeLog	18 Nov 2007 11:08:08 -0000
2007-11-18  Wakaba  <wakaba@suika.fam.cx>

	* Info.pm: New Perl module.

2007-11-18  Wakaba  <wakaba@suika.fam.cx>

	* ChangeLog: New file.


++ manakai/t/ChangeLog	18 Nov 2007 08:41:50 -0000
2007-11-18  Wakaba  <wakaba@suika.fam.cx>

	* DOM-Document.t, DOM-Entity.t: New tests for |manakai_has_bom|
	attribute.

1 wakaba 1.21 ## NOTE: This module will be renamed as Document.pm.
2 wakaba 1.1
3 wakaba 1.21 package Message::DOM::Document;
4     use strict;
5 wakaba 1.25 our $VERSION=do{my @r=(q$Revision: 1.24 $=~/\d+/g);sprintf "%d."."%02d" x $#r,@r};
6 wakaba 1.21 push our @ISA, 'Message::DOM::Node', 'Message::IF::Document',
7     'Message::IF::DocumentTraversal', 'Message::IF::DocumentXDoctype',
8 wakaba 1.22 'Message::IF::DocumentSelector', # MUST in Selectors API spec
9 wakaba 1.21 'Message::IF::HTMLDocument';
10     require Message::DOM::Node;
11     use Char::Class::XML
12     qw/
13     InXML_NameStartChar10 InXMLNameStartChar11
14     InXMLNameChar10 InXMLNameChar11
15     InXML_NCNameStartChar10 InXMLNCNameStartChar11
16     InXMLNCNameChar10 InXMLNCNameChar11
17     /;
18    
19     sub ____new ($$) {
20     my $self = shift->SUPER::____new (undef);
21     $$self->{implementation} = $_[0];
22     $$self->{strict_error_checking} = 1;
23     $$self->{child_nodes} = [];
24     $$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'} = 1;
25     $$self->{'http://suika.fam.cx/www/2006/dom-config/dtd-default-attribute'} = 1;
26     $$self->{'http://suika.fam.cx/www/2006/dom-config/clone-entity-reference-subtree'} = 1;
27     $$self->{'error-handler'} = sub ($) {
28     ## NOTE: Same as one set by |setParameter| with |undef| value.
29     warn $_[0];
30     return $_[0]->severity != 3; # SEVERITY_FATAL_ERROR
31     };
32     return $self;
33     } # ____new
34    
35     sub AUTOLOAD {
36     my $method_name = our $AUTOLOAD;
37     $method_name =~ s/.*:://;
38     return if $method_name eq 'DESTROY';
39 wakaba 1.1
40     if ({
41 wakaba 1.21 ## Read-only attributes (trivial accessors)
42     implementation => 1,
43     }->{$method_name}) {
44     no strict 'refs';
45     eval qq{
46     sub $method_name (\$) {
47     return \${\$_[0]}->{$method_name};
48 wakaba 1.1 }
49 wakaba 1.21 };
50     goto &{ $AUTOLOAD };
51     } elsif ({
52     ## Read-write attributes (DOMString, trivial accessors)
53 wakaba 1.25 manakai_charset => 1,
54 wakaba 1.21 document_uri => 1,
55     input_encoding => 1,
56     }->{$method_name}) {
57     no strict 'refs';
58     eval qq{
59     sub $method_name (\$;\$) {
60     if (\@_ > 1) {
61     if (\${\$_[0]}->{strict_error_checking} and
62     \${\$_[0]}->{manakai_read_only}) {
63     report Message::DOM::DOMException
64     -object => \$_[0],
65     -type => 'NO_MODIFICATION_ALLOWED_ERR',
66     -subtype => 'READ_ONLY_NODE_ERR';
67     }
68     if (defined \$_[1]) {
69     \${\$_[0]}->{$method_name} = ''.\$_[1];
70     } else {
71     delete \${\$_[0]}->{$method_name};
72     }
73     }
74     return \${\$_[0]}->{$method_name};
75 wakaba 1.1 }
76 wakaba 1.21 };
77     goto &{ $AUTOLOAD };
78     } elsif ({
79     ## Read-write attributes (boolean, trivial accessors)
80     all_declarations_processed => 1,
81 wakaba 1.25 manakai_has_bom => 1,
82 wakaba 1.21 }->{$method_name}) {
83     no strict 'refs';
84     eval qq{
85     sub $method_name (\$;\$) {
86     if (\@_ > 1) {
87     if (\${\$_[0]}->{manakai_strict_error_checking} and
88     \${\$_[0]}->{manakai_read_only}) {
89     report Message::DOM::DOMException
90     -object => \$_[0],
91     -type => 'NO_MODIFICATION_ALLOWED_ERR',
92     -subtype => 'READ_ONLY_NODE_ERR';
93     }
94     if (\$_[1]) {
95     \${\$_[0]}->{$method_name} = 1;
96     } else {
97     delete \${\$_[0]}->{$method_name};
98 wakaba 1.1 }
99     }
100 wakaba 1.21 return \${\$_[0]}->{$method_name};
101     }
102     };
103     goto &{ $AUTOLOAD };
104     } elsif (my $module_name = {
105 wakaba 1.23 can_dispatch => 'Message::DOM::EventTargetNode',
106 wakaba 1.21 create_attribute => 'Message::DOM::Attr',
107     create_attribute_ns => 'Message::DOM::Attr',
108     create_attribute_definition => 'Message::DOM::AttributeDefinition',
109     create_cdata_section => 'Message::DOM::Text',
110     create_comment => 'Message::DOM::CharacterData',
111     create_document_fragment => 'Message::DOM::DocumentFragment',
112     create_document_type_definition => 'Message::DOM::DocumentType',
113     create_element => 'Message::DOM::Element',
114     create_element_ns => 'Message::DOM::Element',
115     create_element_type_definition => 'Message::DOM::ElementTypeDefinition',
116     create_entity_reference => 'Message::DOM::EntityReference',
117 wakaba 1.23 create_event => 'Message::DOM::EventTargetNode',
118 wakaba 1.21 create_general_entity => 'Message::DOM::Entity',
119     create_notation => 'Message::DOM::Notation',
120     create_processing_instruction => 'Message::DOM::ProcessingInstruction',
121     manakai_create_serial_walker => 'Message::DOM::SerialWalker',
122     create_text_node => 'Message::DOM::Text',
123     create_tree_walker => 'Message::DOM::TreeWalker',
124 wakaba 1.22 query_selector => 'Message::DOM::SelectorsAPI',
125     query_selector_all => 'Message::DOM::SelectorsAPI',
126 wakaba 1.21 }->{$method_name}) {
127     eval qq{ require $module_name } or die $@;
128     goto &{ $AUTOLOAD };
129     } else {
130     require Carp;
131     Carp::croak (qq<Can't locate method "$AUTOLOAD">);
132 wakaba 1.1 }
133 wakaba 1.21 } # AUTOLOAD
134     sub implementation ($);
135     sub create_attribute ($$);
136     sub create_attribute_ns ($$$);
137     sub create_attribute_definition ($$);
138     sub create_cdata_section ($$);
139     sub create_comment ($$);
140     sub create_document_fragment ($);
141     sub create_document_type_definition ($$);
142     sub create_element ($$);
143     sub create_element_ns ($$$);
144     sub create_element_type_definition ($$);
145     sub create_entity_reference ($$);
146     sub create_general_entity ($$);
147     sub create_notation ($$);
148     sub create_processing_instruction ($$$);
149     sub create_text_node ($$);
150    
151     ## |Node| attributes
152    
153     sub base_uri ($) {
154     my $v = ${$_[0]}->{manakai_entity_base_uri};
155     if (defined $v) {
156     return $v;
157     } else {
158     return ${$_[0]}->{document_uri};
159 wakaba 1.13 }
160 wakaba 1.21 ## TODO: HTML5 <base>
161     } # base_uri
162 wakaba 1.1
163 wakaba 1.21 sub node_name () { '#document' }
164 wakaba 1.1
165 wakaba 1.21 sub node_type () { 9 } # DOCUMENT_NODE
166 wakaba 1.1
167 wakaba 1.21 sub text_content ($;$) {
168     my $self = shift;
169     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
170     return undef;
171 wakaba 1.1 } else {
172 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
173     return $self->SUPER::text_content (@_);
174 wakaba 1.1 }
175 wakaba 1.21 } # text_content
176 wakaba 1.1
177 wakaba 1.21 ## |Node| methods
178 wakaba 1.1
179 wakaba 1.21 sub adopt_node ($$) {
180     my ($self, $source) = @_;
181     ## TODO: Should we apply |copy-asis| configuration parameter to this method?
182 wakaba 1.1
183 wakaba 1.21 return undef unless UNIVERSAL::isa ($source, 'Message::DOM::Node');
184 wakaba 1.1
185 wakaba 1.21 my $strict = $self->strict_error_checking;
186     if ($strict and $$self->{manakai_read_only}) {
187     report Message::DOM::DOMException
188     -object => $self,
189     -type => 'NO_MODIFICATION_ALLOWED_ERR',
190     -subtype => 'READ_ONLY_NODE_ERR';
191     }
192 wakaba 1.1
193 wakaba 1.21 my $parent = $source->parent_node;
194     if ($strict and defined $parent and $$parent->{manakai_read_only}) {
195     report Message::DOM::DOMException
196     -object => $self,
197     -type => 'NO_MODIFICATION_ALLOWED_ERR',
198     -subtype => 'READ_ONLY_NODE_ERR';
199     }
200 wakaba 1.1
201 wakaba 1.21 my $nt = $source->node_type;
202     my $oe;
203     if ($nt == 2) { # ATTRIBUTE_NODE
204     $oe = $source->owner_element;
205     if ($strict and defined $oe and $$oe->{manakai_read_only}) {
206     report Message::DOM::DOMException
207     -object => $self,
208     -type => 'NO_MODIFICATION_ALLOWED_ERR',
209     -subtype => 'READ_ONLY_NODE_ERR';
210     }
211     } elsif ($nt == 9 or $nt == 10 or $nt == 6 or $nt == 12 or
212     $nt == 81001 or $nt == 81002) {
213     # DOCUMENT_NODE, DOCUMENT_TYPE_NODE, ENTITY_NODE, NOTATION_NODE,
214     # ELEMENT_TYPE_DEFINITION_NODE, ATTRIBUTE_DEFINITION_NODE
215     report Message::DOM::DOMException
216     -object => $self,
217     -type => 'NOT_SUPPORTED_ERR',
218     -subtype => 'ADOPT_NODE_TYPE_NOT_SUPPORTED_ERR';
219     ## ISSUE: Define ELEMENT_TYPE_DEFINITION_NODE and ATTRIBUTE_DEFINITION_NODE
220     }
221 wakaba 1.1
222 wakaba 1.21 my @change_od;
223     my @nodes = ($source);
224     while (@nodes) {
225     my $node = shift @nodes;
226     my $nt = $node->node_type;
227     if ($strict and $$node->{manakai_read_only}) {
228     report Message::DOM::DOMException
229     -object => $self,
230     -type => 'NO_MODIFICATION_ALLOWED_ERR',
231     -subtype => 'READ_ONLY_NODE_ERR';
232 wakaba 1.1 }
233    
234 wakaba 1.21 push @change_od, $node;
235     push @nodes, @{$node->child_nodes}, @{$node->attributes or []};
236     } # @nodes
237 wakaba 1.1
238 wakaba 1.21 local $Error::Depth = $Error::Depth + 1;
239 wakaba 1.1
240 wakaba 1.21 if (defined $parent) {
241     $parent->remove_child ($source);
242     } elsif (defined $oe) {
243     $oe->remove_attribute_node ($source);
244     }
245 wakaba 1.1
246 wakaba 1.21 return $source if $self eq $change_od[0]->owner_document;
247     ## NOTE: The array must have more than zero
248     ## nodes by definition. In addition,
249     ## it cannot contain document or document
250     ## type nodes in current implementation.
251 wakaba 1.1
252 wakaba 1.21 my @ud_node;
253     for my $n (@change_od) {
254     $$n->{owner_document} = $self;
255     Scalar::Util::weaken ($$n->{owner_document});
256     if ($$n->{user_data}) {
257     push @ud_node, $n;
258     }
259     }
260 wakaba 1.1
261 wakaba 1.21 for my $src (@ud_node) {
262     my $src_ud = $$src->{user_data};
263     for my $key (keys %{$src_ud}) {
264     my $dh = $src_ud->{$key}->[1];
265     if ($dh) {
266     $dh->(5, $key, $src_ud->{$key}->[0], $src, undef); # NODE_ADOPTED
267 wakaba 1.1 }
268     }
269     }
270    
271 wakaba 1.21 return $source;
272     } # adopt_node
273    
274     sub append_child ($$) {
275     ## NOTE: Overrides |Node|'s implementation.
276     my $self = $_[0];
277 wakaba 1.1
278 wakaba 1.21 ## NOTE: |$self_od| code here in some $self->node_type.
279 wakaba 1.1
280 wakaba 1.21 ## -- Node Type check
281     my @new_child;
282     my $new_child_parent;
283     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
284     push @new_child, @{$_[1]->child_nodes};
285     $new_child_parent = $_[1];
286     } else {
287     @new_child = ($_[1]);
288     $new_child_parent = $_[1]->parent_node;
289     }
290 wakaba 1.1
291 wakaba 1.21 ## NOTE: Depends on $self->node_type:
292     if ($$self->{strict_error_checking}) {
293     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
294     if ($self ne $child_od and $child_od->node_type != 10) {
295     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
296     -object => $self,
297     -type => 'WRONG_DOCUMENT_ERR',
298     -subtype => 'EXTERNAL_OBJECT_ERR';
299     }
300    
301     if ($$self->{manakai_read_only} or
302     (@new_child and defined $new_child_parent and
303     $$new_child_parent->{manakai_read_only})) {
304     report Message::DOM::DOMException
305     -object => $self,
306     -type => 'NO_MODIFICATION_ALLOWED_ERR',
307     -subtype => 'READ_ONLY_NODE_ERR';
308     }
309    
310     ## NOTE: Only in |Document|:
311     my $strict_children = $self->dom_config->get_parameter
312     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
313     if ($strict_children) {
314     my $has_el;
315     my $has_dt;
316     my $child_nt = $_[1]->node_type;
317     if ($child_nt == 1) { # ELEMENT_NODE
318     $has_el = 1;
319     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
320     $has_dt = 1;
321     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
322     for my $cn (@{$_[1]->child_nodes}) {
323     my $cnt = $cn->node_type;
324     if ($cnt == 1) { # ELEMENT_NODE
325     if ($has_el) {
326     report Message::DOM::DOMException
327     -object => $self,
328     -type => 'HIERARCHY_REQUEST_ERR',
329     -subtype => 'CHILD_NODE_TYPE_ERR';
330     }
331     $has_el = 1;
332     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
333     ## NOTE: |DocumentType| node cannot be contained in
334     ## |DocumentFragment| in strict mode.
335     if ($has_dt) {
336     report Message::DOM::DOMException
337     -object => $self,
338     -type => 'HIERARCHY_REQUEST_ERR',
339     -subtype => 'CHILD_NODE_TYPE_ERR';
340     }
341     $has_dt = 1;
342     }
343     }
344     }
345    
346     if ($has_el) {
347     my $anode = $self->last_child;
348     while (defined $anode) {
349     if ($anode->node_type == 1) { # ELEMENT_NODE
350     report Message::DOM::DOMException
351     -object => $self,
352     -type => 'HIERARCHY_REQUEST_ERR',
353     -subtype => 'CHILD_NODE_TYPE_ERR';
354     }
355     $anode = $anode->previous_sibling;
356     }
357     } # has_el
358     if ($has_dt) {
359     my $anode = $self->last_child;
360     while (defined $anode) {
361     my $ant = $anode->node_type;
362     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
363     report Message::DOM::DOMException
364     -object => $self,
365     -type => 'HIERARCHY_REQUEST_ERR',
366     -subtype => 'CHILD_NODE_TYPE_ERR';
367     }
368     $anode = $anode->previous_sibling;
369     }
370     } # has_dt
371     }
372 wakaba 1.1
373 wakaba 1.21 for my $cn (@new_child) {
374     unless ({
375     3, (not $strict_children), # TEXT_NODE
376     5, (not $strict_children), # ENTITY_REFERENCE_NODE
377     1, 1, # ELEMENT_NODE
378     4, (not $strict_children), # CDATA_SECTION_NODE
379     7, 1, # PROCESSING_INSTRUCTION_NODE
380     8, 1, # COMMENT_NODE
381     10, 1, # DOCUMENT_TYPE_NODE
382     }->{$cn->node_type}) {
383     report Message::DOM::DOMException
384     -object => $self,
385     -type => 'HIERARCHY_REQUEST_ERR',
386     -subtype => 'CHILD_NODE_TYPE_ERR';
387     }
388     }
389 wakaba 1.1
390 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
391     }
392 wakaba 1.1
393 wakaba 1.21 ## NOTE: "Insert at" code only in insert_before and replace_child
394 wakaba 1.1
395 wakaba 1.21 ## -- Removes from parent
396     if ($new_child_parent) {
397     if (@new_child == 1) {
398     my $v = $$new_child_parent->{child_nodes};
399     RP: for my $i (0..$#$v) {
400     if ($v->[$i] eq $new_child[0]) {
401     splice @$v, $i, 1, ();
402     last RP;
403     }
404     } # RP
405     } else {
406     @{$$new_child_parent->{child_nodes}} = ();
407     }
408     }
409 wakaba 1.1
410 wakaba 1.21 ## -- Rewrite the |parentNode| properties
411     for my $nc (@new_child) {
412     $$nc->{parent_node} = $self;
413     Scalar::Util::weaken ($$nc->{parent_node});
414     }
415 wakaba 1.1
416 wakaba 1.21 ## NOTE: Depends on method:
417     push @{$$self->{child_nodes}}, @new_child;
418 wakaba 1.1
419 wakaba 1.21 ## NOTE: Only in |Document|.
420     for (@new_child) {
421     delete $$_->{implementation};
422     $$_->{owner_document} = $self;
423     Scalar::Util::weaken ($$_->{owner_document});
424     }
425 wakaba 1.1
426 wakaba 1.21 return $_[1];
427     } # apepnd_child
428 wakaba 1.1
429 wakaba 1.21 sub manakai_append_text ($$) {
430     my $self = shift;
431     if ($$self->{'http://suika.fam.cx/www/2006/dom-config/strict-document-children'}) {
432     #
433     } else {
434     local $Error::Depth = $Error::Depth + 1;
435     return $self->SUPER::manakai_append_text (@_);
436     }
437     } # manakai_append_text
438 wakaba 1.1
439 wakaba 1.21 sub insert_before ($$) {
440     ## NOTE: Overrides |Node|'s implementation.
441     my $self = $_[0];
442 wakaba 1.1
443 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
444 wakaba 1.1
445 wakaba 1.21 ## -- Node Type check
446     my @new_child;
447     my $new_child_parent;
448     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
449     push @new_child, @{$_[1]->child_nodes};
450     $new_child_parent = $_[1];
451     } else {
452     @new_child = ($_[1]);
453     $new_child_parent = $_[1]->parent_node;
454     }
455 wakaba 1.1
456 wakaba 1.21 ## NOTE: Depends on $self->node_type:
457     if ($$self->{strict_error_checking}) {
458     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
459     if ($self ne $child_od and $child_od->node_type != 10) {
460     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
461     -object => $self,
462     -type => 'WRONG_DOCUMENT_ERR',
463     -subtype => 'EXTERNAL_OBJECT_ERR';
464     }
465    
466     if ($$self->{manakai_read_only} or
467     (@new_child and defined $new_child_parent and
468     $$new_child_parent->{manakai_read_only})) {
469     report Message::DOM::DOMException
470     -object => $self,
471     -type => 'NO_MODIFICATION_ALLOWED_ERR',
472     -subtype => 'READ_ONLY_NODE_ERR';
473     }
474    
475     ## NOTE: Only in |Document|:
476     my $strict_children = $self->dom_config->get_parameter
477     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
478     if ($strict_children) {
479     my $has_el;
480     my $has_dt;
481     my $child_nt = $_[1]->node_type;
482     if ($child_nt == 1) { # ELEMENT_NODE
483     $has_el = 1;
484     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
485     $has_dt = 1;
486     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
487     for my $cn (@{$_[1]->child_nodes}) {
488     my $cnt = $cn->node_type;
489     if ($cnt == 1) { # ELEMENT_NODE
490     if ($has_el) {
491     report Message::DOM::DOMException
492     -object => $self,
493     -type => 'HIERARCHY_REQUEST_ERR',
494     -subtype => 'CHILD_NODE_TYPE_ERR';
495     }
496     $has_el = 1;
497     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
498     ## NOTE: |DocumentType| node cannot be contained in
499     ## |DocumentFragment| in strict mode.
500     if ($has_dt) {
501     report Message::DOM::DOMException
502     -object => $self,
503     -type => 'HIERARCHY_REQUEST_ERR',
504     -subtype => 'CHILD_NODE_TYPE_ERR';
505     }
506     $has_dt = 1;
507     }
508     }
509 wakaba 1.1 }
510    
511 wakaba 1.21 ## ISSUE: This code is wrong. Old manakai's implementation
512     ## is better, but it is also wrong in some edge cases.
513     ## Maybe we should remove these code entirely. DOM3Core
514     ## conformance is not important for this bit. It only makes
515     ## things too complex. Same for replace_child's code.
516     if ($has_el) {
517     my $anode = $self->last_child;
518     while (defined $anode) {
519     if ($anode->node_type == 1) { # ELEMENT_NODE
520     report Message::DOM::DOMException
521     -object => $self,
522     -type => 'HIERARCHY_REQUEST_ERR',
523     -subtype => 'CHILD_NODE_TYPE_ERR';
524 wakaba 1.1 }
525 wakaba 1.21 $anode = $anode->previous_sibling;
526 wakaba 1.1 }
527 wakaba 1.21 } # has_el
528     if ($has_dt) {
529     my $anode = $self->last_child;
530     while (defined $anode) {
531     my $ant = $anode->node_type;
532     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
533     report Message::DOM::DOMException
534     -object => $self,
535     -type => 'HIERARCHY_REQUEST_ERR',
536     -subtype => 'CHILD_NODE_TYPE_ERR';
537     }
538     $anode = $anode->previous_sibling;
539     }
540     } # has_dt
541     }
542 wakaba 1.1
543 wakaba 1.21 for my $cn (@new_child) {
544     unless ({
545     3, (not $strict_children), # TEXT_NODE
546     5, (not $strict_children), # ENTITY_REFERENCE_NODE
547     1, 1, # ELEMENT_NODE
548     4, (not $strict_children), # CDATA_SECTION_NODE
549     7, 1, # PROCESSING_INSTRUCTION_NODE
550     8, 1, # COMMENT_NODE
551     10, 1, # DOCUMENT_TYPE_NODE
552     }->{$cn->node_type}) {
553     report Message::DOM::DOMException
554     -object => $self,
555     -type => 'HIERARCHY_REQUEST_ERR',
556     -subtype => 'CHILD_NODE_TYPE_ERR';
557     }
558     }
559 wakaba 1.1
560 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
561     }
562    
563     ## -- Insert at... ## NOTE: Only in insert_before and replace_child
564     my $index = -1; # last
565     if (defined $_[2]) {
566     ## error if $_[1] eq $_[2];
567    
568     my $cns = $self->child_nodes;
569     my $cnsl = @$cns;
570     C: {
571     $index = 0;
572     for my $i (0..($cnsl-1)) {
573     my $cn = $cns->[$i];
574     if ($cn eq $_[2]) {
575     $index += $i;
576     last C;
577     } elsif ($cn eq $_[1]) {
578     $index = -1; # offset
579     }
580     }
581 wakaba 1.1
582 wakaba 1.21 report Message::DOM::DOMException
583     -object => $self,
584     -type => 'NOT_FOUND_ERR',
585     -subtype => 'NOT_CHILD_ERR';
586     } # C
587     }
588     ## NOTE: "else" only in replace_child
589 wakaba 1.1
590 wakaba 1.21 ## -- Removes from parent
591     if ($new_child_parent) {
592     if (@new_child == 1) {
593     my $v = $$new_child_parent->{child_nodes};
594     RP: for my $i (0..$#$v) {
595     if ($v->[$i] eq $new_child[0]) {
596     splice @$v, $i, 1, ();
597     last RP;
598     }
599     } # RP
600     } else {
601     @{$$new_child_parent->{child_nodes}} = ();
602     }
603     }
604 wakaba 1.1
605 wakaba 1.21 ## -- Rewrite the |parentNode| properties
606     for my $nc (@new_child) {
607     $$nc->{parent_node} = $self;
608     Scalar::Util::weaken ($$nc->{parent_node});
609     }
610 wakaba 1.1
611 wakaba 1.21 ## NOTE: Depends on method:
612     if ($index == -1) {
613     push @{$$self->{child_nodes}}, @new_child;
614     } else {
615     splice @{$$self->{child_nodes}}, $index, 0, @new_child;
616     }
617 wakaba 1.1
618 wakaba 1.21 ## NOTE: Only in |Document|.
619     for (@new_child) {
620     delete $$_->{implementation};
621     $$_->{owner_document} = $self;
622     Scalar::Util::weaken ($$_->{owner_document});
623     }
624 wakaba 1.1
625 wakaba 1.21 return $_[1];
626     } # insert_before
627 wakaba 1.1
628 wakaba 1.21 sub replace_child ($$) {
629     ## NOTE: Overrides |Node|'s implementation.
630     my $self = $_[0];
631 wakaba 1.1
632 wakaba 1.21 ## NOTE: |$self_od| code here depending on $self->node_type.
633 wakaba 1.1
634 wakaba 1.21 ## -- Node Type check
635     my @new_child;
636     my $new_child_parent;
637     if ($_[1]->node_type == 11) { # DOCUMENT_FRAGMENT_NODE
638     push @new_child, @{$_[1]->child_nodes};
639     $new_child_parent = $_[1];
640     } else {
641     @new_child = ($_[1]);
642     $new_child_parent = $_[1]->parent_node;
643     }
644 wakaba 1.1
645 wakaba 1.21 ## NOTE: Depends on $self->node_type:
646     if ($$self->{strict_error_checking}) {
647     my $child_od = $_[1]->owner_document || $_[1]; # might be DocumentType
648     if ($self ne $child_od and $child_od->node_type != 10) {
649     report Message::DOM::DOMException # DOCUMENT_TYPE_NODE
650     -object => $self,
651     -type => 'WRONG_DOCUMENT_ERR',
652     -subtype => 'EXTERNAL_OBJECT_ERR';
653     }
654    
655     if ($$self->{manakai_read_only} or
656     (@new_child and defined $new_child_parent and
657     $$new_child_parent->{manakai_read_only})) {
658     report Message::DOM::DOMException
659     -object => $self,
660     -type => 'NO_MODIFICATION_ALLOWED_ERR',
661     -subtype => 'READ_ONLY_NODE_ERR';
662     }
663    
664     ## NOTE: Only in |Document|:
665     my $strict_children = $self->dom_config->get_parameter
666     (q<http://suika.fam.cx/www/2006/dom-config/strict-document-children>);
667     if ($strict_children) {
668     my $has_el;
669     my $has_dt;
670     my $child_nt = $_[1]->node_type;
671     if ($child_nt == 1) { # ELEMENT_NODE
672     $has_el = 1;
673     } elsif ($child_nt == 10) { # DOCUMENT_TYPE_NODE
674     $has_dt = 1;
675     } elsif ($child_nt == 11) { # DOCUMENT_FRAGMENT_NODE
676     for my $cn (@{$_[1]->child_nodes}) {
677     my $cnt = $cn->node_type;
678     if ($cnt == 1) { # ELEMENT_NODE
679     if ($has_el) {
680     report Message::DOM::DOMException
681     -object => $self,
682     -type => 'HIERARCHY_REQUEST_ERR',
683     -subtype => 'CHILD_NODE_TYPE_ERR';
684     }
685     $has_el = 1;
686     } elsif ($cnt == 10) { # DOCUMENT_TYPE_NODE
687     ## NOTE: |DocumentType| node cannot be contained in
688     ## |DocumentFragment| in strict mode.
689     if ($has_dt) {
690     report Message::DOM::DOMException
691     -object => $self,
692     -type => 'HIERARCHY_REQUEST_ERR',
693     -subtype => 'CHILD_NODE_TYPE_ERR';
694     }
695     $has_dt = 1;
696     }
697     }
698     }
699    
700     if ($has_el) {
701     my $anode = $self->last_child;
702     while (defined $anode) {
703     if ($anode->node_type == 1) { # ELEMENT_NODE
704     report Message::DOM::DOMException
705     -object => $self,
706     -type => 'HIERARCHY_REQUEST_ERR',
707     -subtype => 'CHILD_NODE_TYPE_ERR';
708     }
709     $anode = $anode->previous_sibling;
710     }
711     } # has_el
712     if ($has_dt) {
713     my $anode = $self->last_child;
714     while (defined $anode) {
715     my $ant = $anode->node_type;
716     if ($ant == 1 or $ant == 10) { # ELEMENT_NODE or DOCUMENT_TYPE_NODE
717     report Message::DOM::DOMException
718     -object => $self,
719     -type => 'HIERARCHY_REQUEST_ERR',
720     -subtype => 'CHILD_NODE_TYPE_ERR';
721     }
722     $anode = $anode->previous_sibling;
723     }
724     } # has_dt
725     }
726 wakaba 1.1
727 wakaba 1.21 for my $cn (@new_child) {
728     unless ({
729     3, (not $strict_children), # TEXT_NODE
730     5, (not $strict_children), # ENTITY_REFERENCE_NODE
731     1, 1, # ELEMENT_NODE
732     4, (not $strict_children), # CDATA_SECTION_NODE
733     7, 1, # PROCESSING_INSTRUCTION_NODE
734     8, 1, # COMMENT_NODE
735     10, 1, # DOCUMENT_TYPE_NODE
736     }->{$cn->node_type}) {
737     report Message::DOM::DOMException
738     -object => $self,
739     -type => 'HIERARCHY_REQUEST_ERR',
740     -subtype => 'CHILD_NODE_TYPE_ERR';
741     }
742     }
743 wakaba 1.1
744 wakaba 1.21 ## NOTE: Ancestor check here in |Node|.
745     }
746    
747     ## -- Insert at... ## NOTE: Only in insertBefore and replaceChild
748     my $index = -1; # last
749     if (defined $_[2]) {
750     ## error if $_[1] eq $_[2];
751    
752     my $cns = $self->child_nodes;
753     my $cnsl = @$cns;
754     C: {
755     $index = 0;
756     for my $i (0..($cnsl-1)) {
757     my $cn = $cns->[$i];
758     if ($cn eq $_[2]) {
759     $index += $i;
760     last C;
761     } elsif ($cn eq $_[1]) {
762     $index = -1; # offset
763     }
764     }
765 wakaba 1.1
766 wakaba 1.21 report Message::DOM::DOMException
767     -object => $self,
768     -type => 'NOT_FOUND_ERR',
769     -subtype => 'NOT_CHILD_ERR';
770     } # C
771     } else {
772     ## NOTE: Only in replaceChild
773     report Message::DOM::DOMException
774     -object => $self,
775     -type => 'NOT_FOUND_ERR',
776     -subtype => 'NOT_CHILD_ERR';
777     }
778 wakaba 1.1
779     ## -- Removes from parent
780 wakaba 1.21 if ($new_child_parent) {
781     if (@new_child == 1) {
782     my $v = $$new_child_parent->{child_nodes};
783 wakaba 1.1 RP: for my $i (0..$#$v) {
784 wakaba 1.13 if ($v->[$i] eq $new_child[0]) {
785 wakaba 1.1 splice @$v, $i, 1, ();
786     last RP;
787     }
788     } # RP
789 wakaba 1.21 } else {
790     @{$$new_child_parent->{child_nodes}} = ();
791 wakaba 1.1 }
792     }
793    
794     ## -- Rewrite the |parentNode| properties
795     for my $nc (@new_child) {
796 wakaba 1.21 $$nc->{parent_node} = $self;
797     Scalar::Util::weaken ($$nc->{parent_node});
798 wakaba 1.13 }
799 wakaba 1.1
800 wakaba 1.21 ## NOTE: Depends on method:
801     splice @{$$self->{child_nodes}}, $index, 1, @new_child;
802     delete ${$_[2]}->{parent_node};
803 wakaba 1.1
804 wakaba 1.21 ## NOTE: Only in |Document|.
805     for (@new_child) {
806     delete $$_->{implementation};
807     $$_->{owner_document} = $self;
808     Scalar::Util::weaken ($$_->{owner_document});
809     }
810    
811     return $_[2];
812     } # replace_child
813 wakaba 1.1
814 wakaba 1.21 ## |Document| attributes
815 wakaba 1.1
816 wakaba 1.21 ## NOTE: A manakai extension.
817     sub all_declarations_processed ($;$);
818 wakaba 1.1
819 wakaba 1.25 ## TODO: documentation
820     sub manakai_charset ($;$);
821    
822 wakaba 1.21 sub doctype ($) {
823     my $self = $_[0];
824     for (@{$self->child_nodes}) {
825     if ($_->node_type == 10) { # DOCUMENT_TYPE_NODE
826     return $_;
827     }
828     }
829     return undef;
830     } # doctype
831 wakaba 1.1
832 wakaba 1.21 sub document_element ($) {
833     my $self = shift;
834     for (@{$self->child_nodes}) {
835     if ($_->node_type == 1) { # ELEMENT_NODE
836     return $_;
837     }
838     }
839     return undef;
840     } # document_element
841 wakaba 1.1
842 wakaba 1.21 sub document_uri ($;$);
843 wakaba 1.1
844 wakaba 1.21 sub dom_config ($) {
845     require Message::DOM::DOMConfiguration;
846     return bless \\($_[0]), 'Message::DOM::DOMConfiguration';
847     } # dom_config
848 wakaba 1.1
849 wakaba 1.21 sub manakai_entity_base_uri ($;$) {
850     my $self = $_[0];
851     if (@_ > 1) {
852     if ($$self->{strict_error_checking}) {
853     if ($$self->{manakai_read_only}) {
854     report Message::DOM::DOMException
855     -object => $self,
856     -type => 'NO_MODIFICATION_ALLOWED_ERR',
857     -subtype => 'READ_ONLY_NODE_ERR';
858     }
859     }
860     if (defined $_[1]) {
861     $$self->{manakai_entity_base_uri} = ''.$_[1];
862     } else {
863     delete $$self->{manakai_entity_base_uri};
864     }
865     }
866 wakaba 1.1
867 wakaba 1.21 if (defined $$self->{manakai_entity_base_uri}) {
868     return $$self->{manakai_entity_base_uri};
869     } else {
870     return $$self->{document_uri};
871     }
872     } # manakai_entity_base_uri
873 wakaba 1.1
874 wakaba 1.25 ## TODO: documentation
875     sub manakai_has_bom ($;$);
876    
877 wakaba 1.21 sub input_encoding ($;$);
878 wakaba 1.1
879 wakaba 1.21 sub strict_error_checking ($;$) {
880     ## NOTE: Same as trivial boolean accessor, except no read-only checking.
881     if (@_ > 1) {
882     if ($_[1]) {
883     ${$_[0]}->{strict_error_checking} = 1;
884     } else {
885     delete ${$_[0]}->{strict_error_checking};
886     }
887     }
888     return ${$_[0]}->{strict_error_checking};
889     } # strict_error_checking
890 wakaba 1.1
891 wakaba 1.21 ## ISSUE: Setting manakai_is_html true shadows
892     ## xml_* properties. Is this desired?
893 wakaba 1.1
894 wakaba 1.21 sub xml_encoding ($;$) {
895     my $self = $_[0];
896     if (@_ > 1) {
897     ## NOTE: A manakai extension.
898     if ($$self->{strict_error_checking}) {
899     if ($$self->{manakai_is_html}) {
900     report Message::DOM::DOMException
901     -object => $self,
902     -type => 'NOT_SUPPORTED_ERR',
903     -subtype => 'NON_HTML_OPERATION_ERR';
904     }
905     if ($$self->{manakai_read_only}) {
906     report Message::DOM::DOMException
907     -object => $self,
908     -type => 'NO_MODIFICATION_ALLOWED_ERR',
909     -subtype => 'READ_ONLY_NODE_ERR';
910     }
911     }
912     if (defined $_[1]) {
913     $$self->{xml_encoding} = ''.$_[1];
914     } else {
915     delete $$self->{xml_encoding};
916     }
917     }
918    
919     if ($$self->{manakai_is_html}) {
920     return undef;
921     } else {
922     return $$self->{xml_encoding};
923     }
924     } # xml_encoding
925 wakaba 1.1
926 wakaba 1.21 sub xml_standalone ($;$) {
927     my $self = $_[0];
928     if (@_ > 1) {
929     if ($$self->{strict_error_checking}) {
930     if ($$self->{manakai_is_html}) {
931     report Message::DOM::DOMException
932     -object => $self,
933     -type => 'NOT_SUPPORTED_ERR',
934     -subtype => 'NON_HTML_OPERATION_ERR';
935     }
936     ## NOTE: Not in DOM3.
937     if ($$self->{manakai_read_only}) {
938     report Message::DOM::DOMException
939     -object => $self,
940     -type => 'NO_MODIFICATION_ALLOWED_ERR',
941     -subtype => 'READ_ONLY_NODE_ERR';
942     }
943     }
944     if ($_[1]) {
945     $$self->{xml_standalone} = 1;
946     } else {
947     delete $$self->{xml_standalone};
948     }
949     }
950    
951     if ($$self->{manakai_is_html}) {
952     return 0;
953     } else {
954     return $$self->{xml_standalone};
955     }
956     } # xml_standalone
957 wakaba 1.1
958 wakaba 1.21 sub xml_version ($;$) {
959     my $self = $_[0];
960     if (@_ > 1) {
961     my $v = ''.$_[1];
962     if ($$self->{strict_error_checking}) {
963     if ($$self->{manakai_is_html}) {
964     report Message::DOM::DOMException
965     -object => $self,
966     -type => 'NOT_SUPPORTED_ERR',
967     -subtype => 'NON_HTML_OPERATION_ERR';
968     }
969     if ($v ne '1.0' and $v ne '1.1') {
970     report Message::DOM::DOMException
971     -object => $self,
972     -type => 'NOT_SUPPORTED_ERR',
973     -subtype => 'UNKNOWN_XML_VERSION_ERR';
974     }
975     if ($$self->{manakai_read_only}) {
976     ## ISSUE: Not in DOM3.
977     report Message::DOM::DOMException
978     -object => $self,
979     -type => 'NO_MODIFICATION_ALLOWED_ERR',
980     -subtype => 'READ_ONLY_NODE_ERR';
981     }
982     }
983     $$self->{xml_version} = $v;
984     }
985    
986     if (defined wantarray) {
987     if ($$self->{manakai_is_html}) {
988     return undef;
989     } elsif (defined $$self->{xml_version}) {
990     return $$self->{xml_version};
991     } else {
992     return '1.0';
993     }
994     }
995     } # xml_version
996 wakaba 1.1
997 wakaba 1.21 ## |Document| methods
998 wakaba 1.1
999 wakaba 1.21 sub get_element_by_id ($$) {
1000     local $Error::Depth = $Error::Depth + 1;
1001     my @nodes = @{$_[0]->child_nodes};
1002     N: while (@nodes) {
1003     my $node = shift @nodes;
1004     next N unless $node->node_type == 1; # ELEMENT_NODE
1005     for my $attr (@{$node->attributes}) {
1006     if ($attr->is_id and $attr->value eq $_[1]) {
1007     return $node;
1008     }
1009     }
1010     unshift @nodes, @{$node->child_nodes};
1011     } # N
1012     return undef;
1013     } # get_element_by_id
1014 wakaba 1.1
1015 wakaba 1.21 ## TODO: HTML5 case normalization
1016     sub get_elements_by_tag_name ($$) {
1017     my $name = ''.$_[1];
1018     my $chk;
1019     if ($name eq '*') {
1020     $chk = sub () { 1 };
1021     } else {
1022     $chk = sub ($) {
1023     return $_[0]->manakai_tag_name eq $name;
1024     };
1025     }
1026 wakaba 1.1
1027 wakaba 1.21 require Message::DOM::NodeList;
1028     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1029     } # get_elements_by_tag_name
1030 wakaba 1.1
1031 wakaba 1.21 sub get_elements_by_tag_name_ns ($$$) {
1032     my $nsuri = defined $_[1] ? ''.$_[1] : '';
1033     my $lname = ''.$_[2];
1034     my $chk;
1035     if ($nsuri eq '*') {
1036     if ($lname eq '*') {
1037     $chk = sub () { 1 };
1038     } else {
1039     $chk = sub ($) {
1040     return $_[0]->manakai_local_name eq $lname;
1041     };
1042     }
1043     } elsif ($nsuri eq '') {
1044     if ($lname eq '*') {
1045     $chk = sub ($) {
1046     return not defined $_[0]->namespace_uri;
1047     };
1048     } else {
1049     $chk = sub ($) {
1050     return (not defined $_[0]->namespace_uri and
1051     $_[0]->manakai_local_name eq $lname);
1052     };
1053     }
1054     } else {
1055     if ($lname eq '*') {
1056     $chk = sub ($) {
1057     my $ns = $_[0]->namespace_uri;
1058     return (defined $ns and $ns eq $nsuri);
1059     };
1060     } else {
1061     $chk = sub ($) {
1062     my $ns = $_[0]->namespace_uri;
1063     return (defined $ns and $ns eq $nsuri and
1064     $_[0]->manakai_local_name eq $lname);
1065     };
1066     }
1067     }
1068 wakaba 1.1
1069 wakaba 1.21 require Message::DOM::NodeList;
1070     return bless \[$_[0], $chk], 'Message::DOM::NodeList::GetElementsList';
1071     } # get_elements_by_tag_name
1072 wakaba 1.1
1073 wakaba 1.21 ## TODO: import_node
1074 wakaba 1.1
1075 wakaba 1.21 ## TODO: normalize_document
1076 wakaba 1.1
1077 wakaba 1.21 ## TODO: rename_node
1078 wakaba 1.1
1079 wakaba 1.21 ## |DocumentTraversal| methods
1080 wakaba 1.1
1081 wakaba 1.21 ## TODO: create_node_iterator
1082 wakaba 1.1
1083 wakaba 1.21 sub manakai_create_serial_walker ($$;$$$);
1084 wakaba 1.1
1085 wakaba 1.21 sub create_tree_walker ($$;$$$);
1086 wakaba 1.1
1087 wakaba 1.21 ## |HTMLDocument| attributes
1088 wakaba 1.1
1089 wakaba 1.21 sub compat_mode ($) {
1090     if (${$_[0]}->{manakai_is_html}) {
1091     if (defined ${$_[0]}->{manakai_compat_mode} and
1092     ${$_[0]}->{manakai_compat_mode} eq 'quirks') {
1093     return 'BackCompat';
1094     }
1095     }
1096     return 'CSS1Compat';
1097     } # compat_mode
1098 wakaba 1.1
1099 wakaba 1.21 sub manakai_compat_mode ($;$) {
1100     if (${$_[0]}->{manakai_is_html}) {
1101     if (@_ > 1 and defined $_[1] and
1102     {'no quirks' => 1, 'limited quirks' => 1, 'quirks' => 1}->{$_[1]}) {
1103     ${$_[0]}->{manakai_compat_mode} = $_[1];
1104     }
1105     return ${$_[0]}->{manakai_compat_mode} || 'no quirks';
1106 wakaba 1.1 } else {
1107 wakaba 1.21 return 'no quirks';
1108 wakaba 1.1 }
1109 wakaba 1.21 } # manakai_compat_mode
1110 wakaba 1.1
1111 wakaba 1.21 sub inner_html ($;$) {
1112     my $self = $_[0];
1113     local $Error::Depth = $Error::Depth + 1;
1114    
1115     if ($$self->{manakai_is_html}) {
1116     require Whatpm::HTML;
1117     if (@_ > 1) {
1118     ## Step 1
1119     ## TODO: Stop parsing and ...
1120    
1121     ## Step 2
1122     my @cn = @{$self->child_nodes};
1123     for (@cn) { ## NOTE: Might throw a |NO_MODIFICATION_ALLOWED_ERR|.
1124     $self->remove_child ($_); #
1125     }
1126 wakaba 1.1
1127 wakaba 1.21 ## Step 3, 4, 5
1128     Whatpm::HTML->parse_string ($_[1] => $self);
1129 wakaba 1.1
1130 wakaba 1.21 ## TODO:
1131     ## <script>var input = function_to_do_xmlhttprequest (location.href);
1132     ## document.innerHTML = input</script>
1133 wakaba 1.1
1134 wakaba 1.21 return unless defined wantarray;
1135     }
1136 wakaba 1.1
1137 wakaba 1.24 require Whatpm::HTML::Serializer;
1138     return ${ Whatpm::HTML::Serializer->get_inner_html ($self) };
1139 wakaba 1.21 } else {
1140     if (@_ > 1) {
1141     ## Step 1
1142     require Whatpm::XMLParser; # MUST
1143     my $doc = $self->implementation->create_document;
1144    
1145     ## Step 2
1146     #
1147 wakaba 1.1
1148 wakaba 1.21 ## Step 3
1149     $doc = Whatpm::XMLParser->parse_string ($_[1] => $doc); # MUST
1150 wakaba 1.1
1151 wakaba 1.21 ## Step 4
1152     #
1153 wakaba 1.1
1154 wakaba 1.21 ## Step 5
1155     ## TODO: ill-formed -> SYNTAX_ERR # MUST
1156 wakaba 1.1
1157 wakaba 1.21 ## Step 6 # MUST
1158     my @cn = @{$self->child_nodes}; ## TODO: If read-only
1159     for (@cn) {
1160     $self->remove_child ($_);
1161     }
1162 wakaba 1.1
1163 wakaba 1.21 ## Step 7, 8, 9, 10
1164     for my $node (@{$doc->child_nodes}) {
1165     $self->append_child ($self->adopt_node ($node));
1166     }
1167 wakaba 1.1
1168 wakaba 1.21 return unless defined wantarray;
1169     }
1170 wakaba 1.1
1171 wakaba 1.21 ## TODO: This serializer is currently not conformant to HTML5 spec.
1172     require Whatpm::XMLSerializer;
1173     my $r = '';
1174     for (@{$self->child_nodes}) {
1175     $r .= ${ Whatpm::XMLSerializer->get_outer_xml ($_, sub {
1176     ## TODO: INVALID_STATE_ERR
1177     }) };
1178     }
1179     return $r;
1180     }
1181     } # inner_html
1182 wakaba 1.1
1183 wakaba 1.21 sub manakai_is_html ($;$) {
1184     if (@_ > 1) {
1185     if ($_[1]) {
1186     ${$_[0]}->{manakai_is_html} = 1;
1187     } else {
1188     delete ${$_[0]}->{manakai_is_html};
1189     delete ${$_[0]}->{manakai_compat_mode};
1190     }
1191     }
1192     return ${$_[0]}->{manakai_is_html};
1193     } # manakai_is_html
1194 wakaba 1.1
1195 wakaba 1.21 package Message::IF::Document;
1196     package Message::IF::DocumentTraversal;
1197     package Message::IF::DocumentXDoctype;
1198 wakaba 1.22 package Message::IF::DocumentSelector;
1199 wakaba 1.21 package Message::IF::HTMLDocument;
1200 wakaba 1.1
1201 wakaba 1.21 package Message::DOM::DOMImplementation;
1202 wakaba 1.1
1203 wakaba 1.21 sub create_document ($;$$$) {
1204     my $r = Message::DOM::Document->____new ($_[0]);
1205 wakaba 1.1
1206 wakaba 1.21 if (defined $_[2]) {
1207     local $Error::Depth = $Error::Depth + 1;
1208     $r->append_child ($r->create_element_ns ($_[1], $_[2])); # NAMESPACE_ERR
1209     ## NOTE: manakai might raise DOMExceptions in cases not defined
1210     ## in DOM3Core spec: XMLNSPREFIX_NONXMLNSNS_ERR,
1211     ## XMLNS_NONXMLNSNS_ERR, and NONXMLNSPREFIX_XMLNSNS_ERR.
1212     } elsif (defined $_[1]) {
1213     report Message::DOM::DOMException
1214     -object => $_[0],
1215     -type => 'NAMESPACE_ERR',
1216     -subtype => 'QNAME_NULLNS_ERR';
1217     }
1218 wakaba 1.1
1219 wakaba 1.21 if (defined $_[3]) {
1220     if ($_[3]->parent_node) {
1221     report Message::DOM::DOMException
1222     -object => $_[0],
1223     -type => 'WRONG_DOCUMENT_ERR',
1224     -subtype => 'INUSE_DOCTYPE_ERR';
1225     }
1226     local $Error::Depth = $Error::Depth + 1;
1227     $r->insert_before ($_[3], $r->first_child); # EXTERNAL_OBJECT_ERR
1228     }
1229 wakaba 1.1
1230 wakaba 1.21 return $r;
1231     } # create_document
1232 wakaba 1.1
1233 wakaba 1.21 =head1 LICENSE
1234 wakaba 1.1
1235 wakaba 1.21 Copyright 2007 Wakaba <w@suika.fam.cx>
1236 wakaba 1.1
1237 wakaba 1.21 This program is free software; you can redistribute it and/or
1238     modify it under the same terms as Perl itself.
1239 wakaba 1.1
1240 wakaba 1.21 =cut
1241 wakaba 1.1
1242     1;
1243 wakaba 1.25 ## $Date: 2007/11/11 04:23:32 $

admin@suikawiki.org
ViewVC Help
Powered by ViewVC 1.1.24